在将AnsiString的硬类型强制转换替换为TBytes (string数组)后(参见下面),Delphi报告了没有内存泄漏--但是,在TBytes值被传递给具有Pointer类型参数的方法时,TBytes显示了一个泄漏。
以下代码泄漏内存:
program project1;
{$mode delphi}
uses
SysUtils;
function ToBytes(const AValue: AnsiString): TBytes;
begin
SetLength(Result, Length(AValue)); // <-- leak (ine 10)
if Length(AValue) > 0 then
Move(AValue[1], Result[0], Length(AValue));
end;
procedure Send(P: Pointer);
begin
end;
begin
Send(ToBytes('test'));
SetHeapTraceOutput('heaptrace.log');
end. 内存泄漏报告:
Call trace for block $001C5CC0 size 12 $00401586 TOBYTES, line 10
of project1.lpr $00401622 main, line 21 of project1.lpr如果我更改Send方法以接受TBytes类型的参数,内存泄漏就会消失。
发布于 2014-03-04 19:44:23
那是编译器的错误。托管类型TBytes具有引用计数生存期。编译器应该创建一个隐式局部变量,该变量分配给ToBytes返回的数组。您需要通过存储到一个显式的本地来解决这个问题:
var
Tmp: TBytes;
....
Tmp := ToBytes(...);
Send(Tmp);发布于 2014-03-05 13:38:07
它可能不是你所认为的错误。FPC的堆跟踪已经知道了跟踪主程序(主.dpr begin..end)中的温度(以及一般的自动类型)的问题。
将代码移动到一个过程中,并从主begin..end调用它。你就会发现泄漏消失了。
这是因为主程序的一般结构如下
begin
initializeunits(); // procedure call inserted by the compiler
<actual mainprogram statements>
finalizeunits(); // procedure call inserted by the compiler
end.随着主程序温度的发布发生在“结束”。在最终确定的单位,最终堆跟踪。(即使是第一个单位,它仍然只是一个单位)。所以heaptrc想念这个。
发布于 2014-03-04 21:04:57
返回可能包含大量内存的东西的函数使我感到局促不安。这可能只是一种感觉或个人偏好,但它确实剥夺了对记忆分配的控制。对于返回(新构造的) TStringList实例的函数,也有类似的说法,也建议传递指向TStrings对象的指针,并让调用方控制对象的生命周期。
在这里,我建议对TBytes上的所有操作使用var参数,并强制调用方提供要处理的实例。如果您构建了一个复杂的应用程序,而将必须搜索可以提高性能的地方,请再次考虑这一点,看看是否可以回收具有类似内容或长度的TBytes实例。Delphi string系统的一个重要特性是在幕后为您进行引用计数和复制,在应用程序处理大量(类似的)字符串时提供这种性能增益。
https://stackoverflow.com/questions/22181340
复制相似问题