为了消除所有内存泄漏,我试图将LeakCheck库合并到DUnit中。问题是LeakCheck会向我报告不是真正的泄漏的内存泄漏。这些是RTL分配并在程序退出时销毁的对象或其他内容。
LeakCheck包含许多实用的例程,可让您指定要忽略的内容,而我能够使用它们来忽略大多数此类“泄漏”。但是,我不知道该如何特别消除:
#Creating a new event filter
$instanceFilter = ([WMICLASS]"\\.\root\subscription:__EventFilter").CreateInstance()
$instanceFilter.QueryLanguage = "WQL"
$instanceFilter.Query = "SELECT * FROM Win32_ProcessStartTrace"
$instanceFilter.Name = "EventFilter1"
$result = $instanceFilter.Put()
$newFilter = $result.Path
#Creating a new event consumer
$instanceConsumer = ([wmiclass]"\\.\root\subscription:LogFileEventConsumer").CreateInstance()
$instanceConsumer.Name = "EventConsumer1"
$instanceConsumer.FileName = "C:\Scripts\Process_Log.log"
$instanceConsumer.Text = "New process has been created: %TargetInstance.ProcessName%"
$result = $instanceConsumer.Put()
$newConsumer = $result.Path
#Bind filter and consumer
$instanceBinding = ([wmiclass]"\\.\root\subscription:__FilterToConsumerBinding").CreateInstance()
$instanceBinding.Filter = $newFilter
$instanceBinding.Consumer = $newConsumer
$result = $instanceBinding.Put()
创建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
,但结果相同)会导致64字节的内存泄漏:
TThread.CreateAnonymousThread
在其他情况下,LeakCheck为我提供了实例泄漏的类的名称,因此我可以将其添加到被忽略的列表中,但在这种情况下则不会。如何抑制这种“泄漏”?
一个旁注,我所遇到的这种和其他泄漏在GUI应用程序中不会发生。我猜想,RTL在测试运行之前为其中的大多数对象预分配了内存。
答案 0 :(得分:2)
首先查看删除窗体和应用程序后得到的结果。初始化是这样的:
IAP
我从在Spring4D单元测试中使用LeakCheck知道,这来自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?
中某些实例的延迟初始化,这些实例在您的TThread.GetCurrentThread
例程中被调用-更准确地说是在LeakMemory
期间被调用TThread.Destroy
(请参阅Delphi 10.2.3中的WaitFor
行15764)。这将创建您在我发布的报告中看到的实例。
我们在Spring4D中以及在工作中的测试中正在做的事情是在运行任何测试之前调用我们知道会导致实例的一些延迟初始化的各种方法和例程(例如System.Classes.pas
是另一个候选者)。这样可以防止在测试运行期间进行延迟初始化,然后在测试前后将其显示在内存增量中。请参见TEncoding
InitializeLeakCheck
尽管可以将LeakCheck配置为忽略这些泄漏,但由于它将发现泄漏,因此会显着影响性能。如果这些实例是在更改之前初始化的,那么以后就不必忽略了。