我们正试图弄清楚我们的软件是否有内存泄漏。所以,我一直在使用各种工具和程序来帮助我找到可能的内存泄漏。我使用的软件之一是AQTime。随着Delphi XE的推出,它只是一个演示。所以,我真的无法从中获得任何有用的信息。然后,我决定使用自由软件MemProof。到目前为止,它向我展示了我们的软件需要注意的许多问题。其中一个是错误。
一旦我通过MemProof启动我的程序,它就会列出2个错误,它们试图从单元文件system.pas中销毁不存在的对象。所以,当我居然把TObject.Free过程中的破发点,它打破甚至在我的计划开始一路。通过system.pas免费程序步进,我发现TIconimage试图破坏或解脱出来。换句话说,在实际启动之前,我的程序中不会调用自由过程。
这是实际的免费程序:
procedure TObject.Free;
begin
if Self <> nil then
Destroy;
end;
这观察后,我除去断点,让程序运行的所有道路。我的程序主窗口弹出,准备好用户输入。但是,我还发现如果我的程序的WINDOW的任何部分显示在屏幕上,则会不停地调用TObject.Free过程。我根本不明白。这是为什么?谁能解释一下? TForm如何与任何形状或形式的TObject.Free相关,因为当TForm显示在屏幕上时不断调用过程?
提前致谢。
答案 0 :(得分:11)
关于为什么TObject.Free
执行很多,每次销毁一个对象,任何对象,该方法都将被调用。所有类派生自TObject,它是共同的祖先,因此几乎Delphi程序中的任何动作都涉及大量的对象创建/破坏对,因此会命中TObject.Free
。
关于内存泄漏的检测,您需要内置Delphi才能解决此问题。 FastMM内存管理器可以在“报告内存泄漏”模式下运行,它可以为您泄漏的任何内存提供大量诊断。
考虑以下琐碎程序:
program Leaker;
begin
ReportMemoryLeaksOnShutdown := True;
TObject.Create;
end.
这导致以下输出:
您只需要在应用中的某个位置将ReportMemoryLeaksOnShutdown
设置为True(.dpr文件的开头就像任何地方一样好。)
如果您希望在报告中收到更多信息,那么您可以下载full version of FastMM并根据您的内容对其进行配置。
然后你得到这样的输出:
A memory block has been leaked. The size is: 84
This block was allocated by thread 0x1304, and the stack trace (return addresses) at the time was:
40455E [System][System.@GetMem]
405A2F [System][System.TObject.NewInstance]
40602E [System][System.@ClassCreate]
4474C2 [Classes][Classes.TStringList.Create]
C275A3 [Main.pas][Main][Main.TMainForm.CreateAuxiliaryForms][997]
C84C8A [OrcaFlex.dpr][OrcaFlex][OrcaFlex.OrcaFlex][351]
75E633CA [BaseThreadInitThunk]
77519ED2 [Unknown function at RtlInitializeExceptionChain]
77519EA5 [Unknown function at RtlInitializeExceptionChain]
The block is currently used for an object of class: TStringList
真的很棒。它告诉我泄漏的内存是在Main.pas第997行中分配的,这正是我故意泄漏的地方!
答案 1 :(得分:2)
如您所知,TApplication
有Icon
属性,您可以f.i.在项目选项中的应用程序设置中分配。此属性反映在TApplication的FIcon
字段中,该字段在Application
对象的构造函数中创建。 TIcon
有一个TIconImage
字段,表示在其构造函数中创建的实际图像。当Application对象加载并从项目资源文件中分配图标时,必须释放此初始“TIconImage”以防止泄漏。所有这些都发生在项目源中调用Application.Initialize
之前,因为Application对象是从'controls.pas'的初始化部分构造的。
应用程序启动或运行时会发生很多事情。启动时,流机制创建对象(资源流,读取器,类查找器,组件列表......)然后释放它们。运行时,即使是空白的VCL表单(没有控件),每次激活它时都会创建一个列表,以找到一个控件来关注焦点,然后释放此列表。使用复杂的GUI应用程序,即使将鼠标悬停在某些东西上,也可以创建和释放各种图形对象。或者,即使您将鼠标按在某个位置,对齐/排列代码也可以创建/释放对象。
要调试泄漏,您可以参加David's answer概述的课程,或者使用第三方产品专注于泄露的内容,而不是每个创建/释放的对象。 :)
答案 2 :(得分:0)
TObject.Free 。
这包括作为Delphi程序正常执行的一部分创建和销毁的大量对象,包括响应消息由 TForm 对象自动处理的事件由系统生成,只是为了维护窗口对象本身在 Windows 自己的窗口管理器中的存在。
例如,考虑来自 TCustomForm WndProc 的这段代码片段:
WM_MEASUREITEM:
begin
:
Canvas := TControlCanvas.Create;
with Canvas do
try
:
finally
Canvas.Free;
end;
:
end;
这里的关键是响应 WM_MEASUREITEM 消息,自定义表单(因此是标准的 TForm 派生类,因为这最终来自 TCustomForm )创建一个临时的 TControlCanvas ,然后免费完成它。
这可能不一定是您在特定表单中看到的 TObject.Free 调用的来源,它只是一个示例,但显示了如何 TForm 仅仅存在可能导致其他对象被存在并被销毁以响应系统生成的自动消息。