现在,我的理解是字符串是引用计数的,由于没有其他对象参与,导致内存泄漏的原因是什么?在这个StackOverflow问题中,人们找不到造成内存泄漏的方法。
如果没有明显的方法,那么我将下载最新的FastMM源代码(它似乎没有包含在XE源代码中)。
[解决后编辑]找到这个问题的解决方案是安装FastMM源代码,并启用FullDebugMode以获取堆栈跟踪。
现在,我的理解是字符串是引用计数的,由于没有其他对象参与,导致内存泄漏的原因是什么?在这个StackOverflow问题中,人们找不到造成内存泄漏的方法。
如果没有明显的方法,那么我将下载最新的FastMM源代码(它似乎没有包含在XE源代码中)。
[解决后编辑]找到这个问题的解决方案是安装FastMM源代码,并启用FullDebugMode以获取堆栈跟踪。
当使用类型常量并且取决于终结顺序时,FastMM 可能会报告泄漏,而实际上并没有泄漏。
简而言之,当 FinalizedFirst 单元被终结时,SString 常量就会被释放。在单元的终结完成后,FinalizedLast 的终结将被调用。在终结中,它调用 FinalizedFirst 的 LeakMemory 方法。SString 变量再次被初始化,并且不会被释放,因为 FinalizedFirst 的终结已经运行过了。
FinalizedLast Unit
unit FinalizedLast;
interface
uses FinalizedFirst;
implementation
initialization LeakMemory;
finalization LeakMemory;
end.
最终确定的第一个单元
unit FinalizedFirst;
interface
procedure LeakMemory;
implementation
uses FinalizedLast;
procedure LeakMemory;
const
SString: string = '';
begin
//***** SString will get initialized once or twice depending on the
// finalization order of units. If it get's initialized twice,
// a memory leak is reported.
if SString = '' then
SString := 'FooBar';
end;
end.
program LeakMemory;
uses
FastMM4 in 'FastMM4.pas',
Forms,
FinalizedFirst in 'FinalizedFirst.pas',
FinalizedLast in 'FinalizedLast.pas';
{$R *.RES}
begin
Application.Initialize;
Application.Run;
end.
如果使用FreeMem释放堆上的记录而不是Dispose,或者使用System.Move或FillChar覆盖记录,则可能会泄漏字符串。在第一种情况下,终结代码不会运行;在第二种情况下,如果字符串字段已经被填充为nil,则它将认为已经清除了该字段。
如果您想要找到泄漏位置,请下载FastMM并打开FullDebugMode。它将包括泄漏发生位置的堆栈跟踪。
通常情况下,当字符串泄漏时,它们包含在其他未正确销毁的对象中。例如,一个未被释放的对象。然而,您也应该期望看到报告该对象。
解决方法是下载并使用完整版本的FastMM,并配置它在检测到泄漏时报告堆栈跟踪。这样做可以得到分配泄漏对象的完整堆栈跟踪,此时通常就清楚了问题所在。
threadvar
g_szAuthentication : String;
procedure TMyBase.SetAuthentication(szUserName, szPassword: String);
begin
g_szAuthentication := '?name=' + szUserName + '&pass=' + szPassword;
end;