德尔福字符串泄漏

时间:2011-03-24 17:50:59

标签: delphi delphi-xe

我正在使用Delphi XE,并编写一个使用RemObjects SDK进行通信的应用程序(如果可能相关)。我有FastMM调试,有时(并不总是)当我关闭它时会发出关于单个“意外内存泄漏”的警告。 “发生意外的内存泄漏。意外的小块泄漏是:117-124字节:UnicodeString x 1”。偶尔,我会报告x2。

现在,我的理解是字符串是引用计数,并且由于没有其他对象导致泄漏,可能导致这种情况发生的情况是什么?在this StackOverflow question中,人们无法找到泄漏的方法。

如果没有明显的方法,那么我将下载最新的FastMM源(它似乎不包含在XE源中)。

[编辑一旦解决]找到这个的解决方案是安装FastMM源,并启用FullDebugMode来获取堆栈跟踪。

4 个答案:

答案 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的完整版本,并将其配置为在检测到泄漏时报告堆栈跟踪。当你这样做时,你将获得分配泄漏对象的代码的完整堆栈跟踪,此时通常可以清楚问题是什么。