如何使用 LeakCheck 处理 DUnit 中的 "false" / 预期内存?
How to handle "false" / expected memory in DUnit using LeakCheck?
为了消除所有内存泄漏,我试图将 LeakCheck 库合并到 DUnit 中。问题是 LeakCheck 会向我报告并非真正的内存泄漏。这些是由 RTL 分配并在程序退出时销毁的对象或其他东西。
LeakCheck 包含许多例程,允许您指定要忽略的内容,我能够使用它们来忽略其中的大部分 "leaks"。但是,我不知道如何摆脱其中一个:
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:
[=12=]406E76 - LeakCheckMemLeak.exe - System.AllocMem + $A (4562 +25)
[=12=]4C4A53 - LeakCheckMemLeak.exe - System.Classes.TThread.WaitFor + F (15565 +23)
[=12=]5E4EB0 - LeakCheckMemLeak.exe - LeakCheckMemLeak.DetectLeak + (24 +3)
[=12=]5ED5B9 - LeakCheckMemLeak.exe - LeakCheckMemLeak.LeakCheckMemLeak + (35 +3)
3E343D - kernel32.dll
F19832 - ntdll.dll
在其他情况下,LeakCheck 向我提供了 class 实例泄漏的名称,因此我可以将其添加到忽略列表中,但在这种情况下它不会。我怎样才能抑制这个 "leak"?
附带说明一下,我遇到的这个和其他泄漏不会发生在 GUI 应用程序中。我想,RTL 在测试之前为大多数这些对象预分配内存 运行。
FWIW 我在删除 Forms 和 Application.Initialize 后得到的结果是这样的:
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 单元测试中使用 LeakCheck 了解到,这来自 TThread.GetCurrentThread
中某些实例的延迟初始化,这些实例在 LeakMemory
例程期间被调用 - 更准确地说是在 TThread.Destroy
期间它调用 WaitFor
(请参阅 Delphi 10.2.3 中的 System.Classes.pas
行 15764)。这会创建您在我发布的报告中看到的实例。
我们在 Spring4D 中以及在工作中的测试中所做的是在 运行宁任何测试。这可以防止在测试 运行 期间进行延迟初始化,然后在测试前后在内存增量中显示出来。请参阅 Spring.TestRunner.pas
中的 InitializeLeakCheck
虽然您可以将 LeakCheck 配置为忽略这些泄漏,但它会显着影响性能,因为它会首先发现泄漏。如果这些实例在更改之前被初始化,那么以后就没有什么可以忽略的了。
为了消除所有内存泄漏,我试图将 LeakCheck 库合并到 DUnit 中。问题是 LeakCheck 会向我报告并非真正的内存泄漏。这些是由 RTL 分配并在程序退出时销毁的对象或其他东西。
LeakCheck 包含许多例程,允许您指定要忽略的内容,我能够使用它们来忽略其中的大部分 "leaks"。但是,我不知道如何摆脱其中一个:
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:
[=12=]406E76 - LeakCheckMemLeak.exe - System.AllocMem + $A (4562 +25)
[=12=]4C4A53 - LeakCheckMemLeak.exe - System.Classes.TThread.WaitFor + F (15565 +23)
[=12=]5E4EB0 - LeakCheckMemLeak.exe - LeakCheckMemLeak.DetectLeak + (24 +3)
[=12=]5ED5B9 - LeakCheckMemLeak.exe - LeakCheckMemLeak.LeakCheckMemLeak + (35 +3)
3E343D - kernel32.dll
F19832 - ntdll.dll
在其他情况下,LeakCheck 向我提供了 class 实例泄漏的名称,因此我可以将其添加到忽略列表中,但在这种情况下它不会。我怎样才能抑制这个 "leak"?
附带说明一下,我遇到的这个和其他泄漏不会发生在 GUI 应用程序中。我想,RTL 在测试之前为大多数这些对象预分配内存 运行。
FWIW 我在删除 Forms 和 Application.Initialize 后得到的结果是这样的:
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 单元测试中使用 LeakCheck 了解到,这来自 TThread.GetCurrentThread
中某些实例的延迟初始化,这些实例在 LeakMemory
例程期间被调用 - 更准确地说是在 TThread.Destroy
期间它调用 WaitFor
(请参阅 Delphi 10.2.3 中的 System.Classes.pas
行 15764)。这会创建您在我发布的报告中看到的实例。
我们在 Spring4D 中以及在工作中的测试中所做的是在 运行宁任何测试。这可以防止在测试 运行 期间进行延迟初始化,然后在测试前后在内存增量中显示出来。请参阅 Spring.TestRunner.pas
InitializeLeakCheck
虽然您可以将 LeakCheck 配置为忽略这些泄漏,但它会显着影响性能,因为它会首先发现泄漏。如果这些实例在更改之前被初始化,那么以后就没有什么可以忽略的了。