我正在使用Delphi XE,并编写一个使用RemObjects SDK进行通信的应用程序(如果可能相关)。我有FastMM调试,有时(并不总是)当我关闭它时会发出关于单个“意外内存泄漏”的警告。 “发生意外的内存泄漏。意外的小块泄漏是:117-124字节:UnicodeString x 1”。偶尔,我会报告x2。
现在,我的理解是字符串是引用计数,并且由于没有其他对象导致泄漏,可能导致这种情况发生的情况是什么?在this StackOverflow question中,人们无法找到泄漏的方法。
如果没有明显的方法,那么我将下载最新的FastMM源(它似乎不包含在XE源中)。
[编辑一旦解决]找到这个的解决方案是安装FastMM源,并启用FullDebugMode来获取堆栈跟踪。
答案 0 :(得分:7)
当使用类型化常量并依赖于最终化顺序时,FastMM可能会在确实没有时报告泄漏。
FastMM: Leaked memory reported where I believe it shouldn't.
简而言之,当FinalizedFirst单位时 得到最终确定,SString常量 得到了自由。完成后 单位完成,最终确定 FinalizedLast得到了调用。在它是 最终确定,它称之为方法 FinalizedFirst的LeakMemory 方法。 SString变量得到 再次初始化,但没有得到 释放为最终定稿 FinalizedFirst已经运行。
FinalizedLast Unit
unit FinalizedLast;
interface
uses FinalizedFirst;
implementation
initialization LeakMemory;
finalization LeakMemory;
end.
FinalizedFirst Unit
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.
Project LeakMemory
program LeakMemory;
uses
FastMM4 in 'FastMM4.pas',
Forms,
FinalizedFirst in 'FinalizedFirst.pas',
FinalizedLast in 'FinalizedLast.pas';
{$R *.RES}
begin
Application.Initialize;
Application.Run;
end.
答案 1 :(得分:6)
您可以通过使用FreeMem而不是Dispose释放堆上的记录或使用System.Move或FillChar覆盖记录来泄漏字符串。在第一种情况下,终止代码没有运行,而在第二种情况下,如果字符串字段填充了nil,它会认为它已经被清除了。
如果要查找泄漏下载FastMM的位置并启用FullDebugMode。它将包括泄漏发生位置的堆栈跟踪。
答案 2 :(得分:5)
我想到的唯一方法是在不故意破坏字符串的情况下泄漏字符串(例如手动递增引用计数或执行一些混乱的指针操作)是使用threadvar。
与帮助文件状态一样,
通常的动态变量 由编译器管理(长字符串, 宽字符串,动态数组, 变体和接口)可以 用threadvar声明,但是 编译器不会自动释放 由堆创建的堆分配的内存 每个执行线程。如果你使用 这些数据类型在线程变量中, 你有责任处置 从他们内心的记忆 线程,在线程终止之前。
除此之外,没有任何想到的事情还没有说明。
[提问者编辑]这确实是个问题,具体代码如下:
threadvar
g_szAuthentication : String;
procedure TMyBase.SetAuthentication(szUserName, szPassword: String);
begin
g_szAuthentication := '?name=' + szUserName + '&pass=' + szPassword;
end;
答案 3 :(得分:4)
当它们被包含在未被正确销毁的其他对象中时,我通常会看到字符串泄漏。例如,尚未释放的对象。但是,您也希望看到该对象也被报告。
解决此问题的方法是下载并使用FastMM的完整版本,并将其配置为在检测到泄漏时报告堆栈跟踪。当你这样做时,你将获得分配泄漏对象的代码的完整堆栈跟踪,此时通常可以清楚问题是什么。