【问题标题】:how to RegisterExpectedMemoryLeak如何注册预期的内存泄漏
【发布时间】:2024-08-07 04:20:01
【问题描述】:

让我们从 D2010 下的简单代码开始:

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

FastMM4 一次又一次地报告内存泄漏,即使使用Addr(StringList) 作为参数 那么如何注册 Expected MemoryLeak 以及为什么上面的方法不起作用 提前谢谢。

【问题讨论】:

    标签: delphi delphi-2010 fastmm


    【解决方案1】:

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

    说起来容易做起来难。因为你需要找到代表字符串的内存块的开始。这与字符串的第一个字符有一个固定的偏移量,偏移量取决于您使用的 Delphi 版本。

    在 Unicode Delphi 中,在 32 位代码中,偏移量是 12 个字节。所以下面会注册泄露的字符串:

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

    即使您这样做了,您仍然会收到两次报告的内存泄漏。其中至少一个由字符串列表TStringList.FList 拥有的动态数组解释。如果您想注册该泄漏,那么您将需要做更多的黑客攻击,因为您将不得不再次依赖实现细节来确定该数组的存储位置。

    【讨论】:

    • 这比我第一眼看到的要复杂一些谢谢大卫。
    • 也许你可以写一个TLeakyStringList 可以使用它的内部知识来注册自己。那是多么的OOP? ;-)