如何注册预期内存泄漏?

4

让我们从这个简单的 Delphi 2010 片段开始:

var
  StringList: TStringList;
begin
  ReportMemoryLeaksOnShutdown := True;
  StringList := TStringList.Create;
  StringList.LoadFromFile('c:\fateh.txt');
  RegisterExpectedMemoryLeak(StringList);

快速内存管理器(FastMM4)报告内存泄漏,即使使用Addr(StringList)作为参数。那么如何注册预期的内存泄漏,同时为什么上面的方法不起作用?谢谢提前。

不要忘记在TStringList.Create之后使用Try(当然还有相应的Finally)。 - Gabriel
1个回答

4

您只注册了字符串列表对象的泄漏,还需要注册您正在泄漏的所有由字符串列表拥有的对象。在这种情况下,它拥有StringList.Countstring对象实例。内存管理器不知道这些字符串是由字符串列表对象拥有的,因此也会被泄漏。

这比说起来要容易得多。因为您需要找到表示字符串的内存块的起始位置。这在字符串的第一个字符的固定偏移量处,并且偏移量取决于您使用的Delphi版本。

在Unicode Delphi中,在32位代码中,偏移量为12个字节。因此,以下内容将注册泄漏的字符串:

for i := 0 to StringList.Count-1 do 
  if StringList[i]<>'' then
    RegisterExpectedMemoryLeak(PByte(StringList[i])-12);

即使这样做,仍然会报告两个内存泄漏。其中至少一个是由字符串列表拥有的动态数组 TStringList.FList 解释的。如果要注册该泄漏,则需要进行更多的操作,因为您必须再次依赖于实现细节以确定该数组存储在何处。

这比我第一眼看到的要复杂一些,谢谢David。 - S.FATEH
也许你可以编写一个TLeakyStringList,它可以利用其内部知识来注册自己。这是多么面向对象啊!;-) - Warren P

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接