修复内存泄漏问题

3
最近我发现 Delphi 有一个全局变量叫做 ReportMemoryLeaksOnShutdown,当设置为 True 时,会在应用程序关闭时检测内存泄漏。我从阅读另一个相关问题的一些评论中发现了这些信息:What is the best tool to detect memory leaks in Delphi
所以我在项目源代码中加入了 ReportMemoryLeaksOnShutdown := True; 现在当我的应用程序关闭时,它会检测到很多内存泄漏。我的第一反应是检查是否正确释放了创建的对象(使用 try..finally..free 等)。
我已经仔细检查了代码,但我看不出泄漏可能来自哪里,现在我需要找到它们,因为如果应用程序退出时报告内存泄漏,则非常意味着运行时存在内存泄漏,这将增加大小并且是不好的!
从上面的链接中推荐了第三方工具,如 Eureka Log。是否有一种只使用 IDE 和调试器的方法来帮助我找到和修复问题区域?
更新
我成功解决了大约6个内存泄漏问题,发现与 MDI 子窗口有关。这些子窗口在列表框中保存了一些指针数据,在主应用程序关闭时,它没有正确释放子窗口,现在已经解决了。
现在我还剩下这两个错误:

enter image description here

我发现了这篇文章http://fgaillard.com/2011/02/when-the-debugger-leaks/,它可能表明调试器是导致我上述错误的罪魁祸首?

5
阅读 how-to-get-a-stack-trace-from-fastmm。我会为您翻译内容并尽力保持原文意思的清晰度和易懂性。 - LU RD
如果您拥有Delphi XE Architect或Enterprise,或者XE2 Arch/Ent版本,则拥有AQTime,它具有比FastMM更好的泄漏定位技术,包括一个漂亮的GUI,可以制作可视化列表,并通过单击将您带到泄漏处。 - Warren P
1
我只在应用程序关闭时出现Access Violation,但从未显示(实际上应用程序无法正常退出,它强制关闭并抑制了Access Violation消息)时才会看到UnicodeString泄漏。请检查确保您没有释放已经被释放的对象!根据我的经验,这是一个常见的原因! - LaKraven
是的,调试器会泄漏UnicodeStrings。这有点烦人! - David Heffernan
2
我认为它从工具提示中泄漏了字符串。没关系。不要使用调试器运行,如果您仍然看到这些泄漏,则它们是真实的。 - David Heffernan
显示剩余4条评论
2个回答

19
首先,确保您获得了完整版FastMM。它具有一些额外的功能,例如FullDebugMode,这将对您有所帮助。在编译器选项中定义FullDebugMode和'LogMemoryLeaksToFile'设置,并在与EXE相同的文件夹中使用FullDebugMode DLL重新构建项目。这将生成一个文件,在程序关闭时提供有关内存泄漏的详细信息,除了对话框。这里最有用的信息将是每个分配的部分堆栈跟踪。
一旦您拥有了这些信息,就可以开始修复内存泄漏。这需要一些技巧:记住对象所有权通常看起来很像一棵树:一个对象拥有其他对象,每个对象都拥有其他对象,依此类推。因此,您要首先查找最少泄漏数量的泄漏类型,因为那很可能是树的根。
例如,如果报告说您泄漏了一个TObjectList和1000个TMyObject实例,那么很可能这些TMyObject实例被分配给列表,而您只是忘记释放列表。修复这个问题将清除整个报告,因此在排除其他事情之前不要寻找单独的子对象。

7

最好的方法是让工具告诉你哪里发生了泄漏所导致的分配位置。为此,您需要下载并使用完整版FastMM。Delphi附带的版本没有此功能。

在使用完整的FastMM时,将生成一份报告,其中包含您需要的所有详细信息,包括堆栈跟踪,以告诉您哪个代码片段出现了泄漏。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接