代码之家  ›  专栏  ›  技术社区  ›  Wodzu

如何使用泄漏检查处理dunit中的“假/预期内存”?

  •  2
  • Wodzu  · 技术社区  · 6 年前

    为了消除所有内存泄漏,我正在尝试合并 LeakCheck 图书馆变成了邓尼特。问题是,LeakCheck会向我报告不是真正泄漏的内存泄漏。这些是RTL分配的对象或其他东西,在程序退出时被销毁。

    LeakCheck包含了许多允许您指定忽略什么的例程,我可以使用它们来忽略大多数此类“泄漏”。但是,我不知道如何摆脱一个特别的:

    program LeakCheckMemLeak;
    {$APPTYPE CONSOLE}
    uses
      LeakCheck, TestFramework, LeakCheck.DUnit, LeakCheck.Utils,  LeakCheck.Setup.Trace, System.SysUtils,
      Forms, System.Classes;
    
    {$R *.RES}
    
    procedure LeakMemory;
    var
      LThread: TThread;
    begin
      LThread := TThread.Create(True);
      LThread.Free;
    end;
    
    procedure DetectLeak;
    var
      Snapshot: TLeakCheck.TSnapshot;
      Report: LeakString;
    begin
      Snapshot.Create;
      LeakMemory;
      Report := TLeakCheck.GetReport(Snapshot.Snapshot);
      try
        Writeln(string(Report));
      finally
        Report.Free;
      end;
    end;
    
    begin
      Application.Initialize;
      DetectLeak;
      Readln;
    end.
    

    正在创建的实例 TThread (原来是 TThread.CreateAnonymousThread 但结果相同)导致64字节内存泄漏:

    Total allocation count: 297 (12592 B)
    Leak detected 02BB3DC0 size 64 B
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 E8 03 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ????????????????????????????????
      00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 | ????????????????????????????????
    Stack trace when the memory block was allocated:
      $00406E76 - LeakCheckMemLeak.exe - System.AllocMem + $A (4562 +25)
      $004C4A53 - LeakCheckMemLeak.exe - System.Classes.TThread.WaitFor + $8F (15565 +23)
      $005E4EB0 - LeakCheckMemLeak.exe - LeakCheckMemLeak.DetectLeak + $34 (24 +3)
      $005ED5B9 - LeakCheckMemLeak.exe - LeakCheckMemLeak.LeakCheckMemLeak + $29 (35 +3)
      $763E343D - kernel32.dll
      $76F19832 - ntdll.dll
    

    在其他情况下,leackcheck提供了实例泄漏的类的名称,以便将其添加到忽略列表中,但在本例中,它没有提供。我怎么能阻止这个“泄露”?

    一个附带说明,我遇到的这个和其他泄漏不会在GUI应用程序中发生。我猜,在测试运行之前,RTL会预先分配大多数这些对象的内存。

    1 回复  |  直到 6 年前
        1
  •  2
  •   Stefan Glienke    6 年前

    fwiw删除窗体和应用程序后得到的结果。初始化如下:

    Total allocation count: 113 (4152 B)
    Leak detected 0262F540 size 44 B for class: TExternalThread
    Leak detected 0260A988 size 20 B for class: TThreadList<System.Classes.TThread>
    Leak detected 02618A90 size 8 B for class: TObject
    Leak detected 026451F8 size 52 B for class: TList<System.Classes.TThread>
    Leak detected 02618AC8 size 12 B
      01 00 00 00 01 00 00 00 40 F5 62 02 | ????????@?b?
    

    我通过在Spring4d单元测试中使用leackcheck知道这是由于在 TThread.GetCurrentThread 在您的 LeakMemory 常规-更准确地说 TThread.Destroy 哪个电话 WaitFor (见 System.Classes.pas Delphi 10.2.3中的第15764行)。这将创建您在我发布的报告中看到的实例。

    我们在Spring4d以及工作中的测试中所做的就是调用各种方法和例程,我们知道这些方法和例程会导致一些实例的延迟初始化。( TEncoding 例如,在运行任何测试之前。这可以防止测试运行期间的延迟初始化,然后在测试前后在内存增量中显示。见 InitializeLeakCheck 在里面 Spring.TestRunner.pas

    虽然可以将LeackCheck配置为忽略这些泄漏,但它将显著影响性能,因为它会首先发现泄漏。如果在更改之前初始化了这些实例,那么以后就没有什么可忽略的了。