使用FastMM了解内存分配的位置

6

我正在使用Delphi 7调试一个大型应用程序的内存使用情况。我已经成功安装了fastmm debug full dll,并解决了一些泄漏问题。

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

我的问题是,有没有办法找出这些块是在哪里分配的?我知道这是可能的,因为如果内存没有被释放,会打印出堆栈跟踪。有没有一种方法可以“poke” fastmm,使其打印给定分配的堆栈跟踪?

附带问题:如果已知分配的起始地址,有没有办法找出对象所属的类?(假设分配是为对象进行的)。

3个回答

5
你可以选择:
  • 尝试使用LogAllocatedBlocksToFile过程。如果它的ALastAllocationGroupToLog参数小于AFirstAllocationGroupToLog或为零,则记录所有块以及它们的分配调用堆栈。但是,如果您的应用程序有许多内存分配,请准备等待很长时间。我经历了大约4小时的等待时间和1.5GB的结果文件。(附注:使用glogg查看这样大的文件)
  • 修改FastMM4.pas,使实现的LogCallStack在接口中可见。或者你可以直接从FastMM_FullDebugMode.dll中使用它。
另外一个问题:尝试使用DetectClassInstance函数。

2
如果你使用FullDebugMode并启用条件语句来将数据写入文件,那么你应该会得到你所要求的精确结果。它将在程序关闭时为每个泄漏的分配记录一个堆栈跟踪。(如果你正在调试一个有很多内存泄漏的程序,这可能需要一段时间。如果泄漏项是一个包含许多其他对象的容器,我曾看到它使关闭时间延长10分钟或更长时间。)

是的,我现在明白了,但我遇到的问题是当我关闭应用程序时,所有的内存都被很好地清理了 - 我想知道在应用程序加载完毕时的某个时间点的信息。 - wmercer

2
考虑到你在评论中说应用程序在关闭时会很好地清理内存,因此对我来说,您正在寻找逻辑内存泄漏——换句话说:对象比需要的时间更长时间存在,但当时间到达要结束应用程序时,它们会被清理,因为存在清理它们的代码。
例如:
创建一个TForm,使用Application作为所有者,并且引用它的变量是 Delphi 在创建窗体单元时创建的全局变量。
将Form的CloseAction配置为caHide(在OnClose事件中)。
显示表单,在其上操作。
关闭窗体并再也不使用它,直到应用程序关闭为止。
关闭应用程序,这使得Application清除其拥有的所有对象。
所以你有一个逻辑内存泄漏,但不是物理内存泄漏——这是FastMM可以轻松检测到的那种。由于您不打算让我们假设的TForm一直存在,因此它在语义上泄漏,但由于它被引用并且存在代码在应用程序结束时摧毁它,因此对于FastMM而言,这是正常分配。
也就是说,您似乎不需要内存管理器的内存转储,而是需要一个内存分析工具。

谢谢您提供详细的答案,Delphi 有内存分析器这样的工具吗? - wmercer
1
@emuduguntar: AQTime 是我所知道的 Delphi 唯一的内存分析器,除了 FastMM 本身。 - Serhii Kheilyk

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