6

我正在尝试使用 Delphi 7 调试大型应用程序中的内存使用情况。我能够安装 fastmm debug full dll 并解决一些泄漏问题。

我还安装了内存使用跟踪器,让我可以查看分配了哪些块以及它们的大小。

我的问题是,有没有办法找出块的分配位置?我知道这是可能的,因为如果没有释放内存,则会打印堆栈跟踪。有没有办法“戳”fastmm 让它打印给定分配的堆栈跟踪?

附带问题:如果知道分配的起始地址,有没有办法找出对象是哪个类?(假设分配是针对一个对象的。

4

3 回答 3

5

您可以:

  • 尝试使用LogAllocatedBlocksToFile程序。如果其ALastAllocationGroupToLog参数小于AFirstAllocationGroupToLog或为零,则记录所有块及其分配调用堆栈。但是,如果您的应用程序有很多内存分配,请准备好长时间等待。我经历了大约 4 小时的等待时间和 1.5Gb 的结果文件。(旁注:使用glogg查看如此大的文件)
  • 修改FastMM4.pas以便实现LogCallStack将在界面中可见。或者您可以尝试直接从FastMM_FullDebugMode.dll

附带问题:尝试使用DetectClassInstance函数。

于 2013-01-19T03:24:54.880 回答
2

如果您使用 FullDebugMode 并启用将数据写入文件的条件,那么您应该得到您想要的。当程序关闭时,它将为每个泄漏的分配写出堆栈跟踪。(如果您正在调试一个存在大量内存泄漏的程序,这可能需要一段时间。如果泄漏的项目是一个包含许多其他对象的容器,我认为它会使关闭持续 10 分钟或更长时间。)

于 2013-01-18T01:09:28.110 回答
2

考虑到您在评论中说应用程序的内存在应用程序关闭时得到了很好的清理,听起来您正在寻找逻辑内存泄漏 - 换句话说:对象的存活时间比需要的时间长,但时间到了完成应用程序它们被清理是因为存在清理它们的代码。

例子:

  • 使用 Application 作为所有者创建一个 TForm,引用它的变量是 Delphi 在创建表单单元时创建的全局变量。
  • 将表单的 CloseAction 配置为 caHide(在 OnClose 事件中)
  • 显示表格,对其进行操作
  • 关闭表单,在应用关闭之前不再使用它
  • 关闭应用程序,这会使应用程序清除它拥有的所有对象

所以你有逻辑内存泄漏,但没有物理内存泄漏——这是 FastMM 可以轻松检测到的那种。由于您不希望我们假设的 TForm 在应用程序完成之前一直存在,因此它在语义上泄漏了,但是由于它被引用并且在应用程序结束时有代码破坏它,因此对于 FastMM 来说是一个正常的分配。

也就是说,您似乎不需要内存管理器的内存转储,而是内存分析器。

于 2013-01-18T19:09:23.533 回答