【问题标题】:Fixing Memory Leaks修复内存泄漏
【发布时间】:2012-01-12 14:04:11
【问题描述】:

我最近发现 Delphi 有一个名为 ReportMemoryLeaksOnShutdown 的全局变量,当设置为 True 时会在应用程序关闭时检测内存泄漏。我从另一个相关问题上阅读了一些 cmets 发现了这些信息:What is the best tool to detect memory leaks in Delphi

所以我从项目源中输入ReportMemoryLeaksOnShutdown := True;

现在,当我的应用程序关闭时,它会发现大量内存泄漏。我的直接想法是检查创建的对象是否被正确释放(try..finally..free 等)。

我已经检查了代码,但看不到泄漏可能来自哪里,现在我需要找到它们,因为如果在退出应用程序时报告内存泄漏,那么这非常意味着内存泄漏运行时,它会变大并且很糟糕!

从上面的链接中推荐了 3rd 方工具,例如 Eureka Log。有没有办法只使用 IDE 和调试器来帮助我找到并修复问题区域?

更新

我设法摆脱了大约 6 次内存泄漏,我发现这与 MDI Childs 有关。子级在列表框中保存了一些指针数据,当主应用程序关闭时,它没有正确释放子级,现在已修复。

我现在有这两个错误:

我发现这篇帖子 http://fgaillard.com/2011/02/when-the-debugger-leaks/ 可能表明调试器出现了我的上述错误?

【问题讨论】:

  • 也许没有真正的泄漏,但您之前分配的一些静态对象仍在内存中,而应用程序关闭。
  • 首先要注意的是,如果创建基于 TComponent 的对象(包括控件)总是将父控件传递给构造函数,则无需担心它们。 Delphi 负责为您发布这些内容。但是,如果您有任何 TPersistent 或 TObject 后代,则需要手动释放它们。泄漏报告对话框应该告诉你负责泄漏的类名!
  • 我只看到 UnicodeString 泄漏,当应用程序在关闭时访问冲突从不显示(本质上应用程序没有正确退出,它强制自身关闭以抑制访问冲突消息)。检查以确保您没有释放已经释放的对象!根据我的经验,这是一个常见的原因!
  • 我认为它会从工具提示中泄漏字符串。不管。在没有调试器的情况下运行,如果您仍然看到这些泄漏,那么它们是真实的。

标签: delphi memory-leaks


【解决方案1】:

首先,确保您收到the full version of FastMM。它有一些额外的功能,例如FullDebugMode,这将在这里为您提供帮助。使用编译器选项中定义的FullDebugMode 和“LogMemoryLeaksToFile”设置以及与 EXE 位于同一文件夹中的 FullDebugMode DLL 重新构建您的项目。除了对话框之外,这将生成一个文件,其中包含有关程序关闭时内存泄漏的详细信息。这里最有用的信息是每个分配的部分堆栈跟踪。

获得这些信息后,您就可以开始修复内存泄漏了。这有一点技巧:请记住,对象所有权通常看起来很像一棵树:一个对象拥有其他对象,这些对象又拥有其他对象,依此类推。因此,您首先要查找的是泄漏数量最少的泄漏类型,因为它很可能是树的根。

例如,如果报告说您泄漏了一个 TObjectList 和 1000 个 TMyObject 实例,则很可能这些 TMyObject 实例已分配给该列表,而您只是忘记释放该列表。解决这个问题会清除整个报告,所以在排除其他事情之前不要四处寻找单个子对象。

【讨论】:

    【解决方案2】:

    执行此操作的最佳方法是让该工具判断导致泄漏的分配位置。为此,您需要下载并使用完整版 FastMM。 Delphi 提供的版本没有这个功能。

    使用完整的 FastMM 时,将生成一份报告,其中包含您需要的所有血腥细节,包括堆栈跟踪,告诉您哪段代码泄露了。

    【讨论】:

      猜你喜欢
      • 2013-07-29
      • 2017-07-29
      • 2012-03-26
      • 1970-01-01
      • 1970-01-01
      • 2012-09-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多