德尔福 FastMM4 如何阅读MemoryManager_EventLog.txt?



我已将 FastMM4 添加到我的项目中以检测内存泄漏

program MyProg;
uses
{$IFDEF DEBUG}
FastMM4,
{$ENDIF}
...other uses

在形式关闭时,FastMM4产生MemoryManager_EventLog.txt,所有泄漏堵塞。

这是一个示例:

--------------------------------2019/6/19 9:49:25--------------------------------
A memory block has been leaked. The size is: 20
This block was allocated by thread 0x558, and the stack trace (return addresses) at the time was:
4075D2 [System.pas][System][@GetMem$qqri][4614]
40ABAF [System.pas][System][TObject.NewInstance$qqrv][16452]
40B3D6 [System.pas][System][@ClassCreate$qqrpvzc][17790]
40AD20 [System.pas][System][TObject.$bctr$qqrv][16516]
F3BEF6 [NdST.pas][NdST][TFinder.$bctr$qqrp14System.TObject][1011]
11157D1 [SuperNode.pas][SuperNode][TSuperNode.$bctr$qqrp14System.TObject][993]
D1D840 [Network.pas][Network][TNetwork.Create$qqrv][968]
F3A70D [NdST.pas][NdST][TNdST.$bctr$qqrp14System.TObject][177]
F3B658 [NdST.pas][NdST][TNdSTCAP.$bctr$qqrp14System.TObject][652]
10A4CCA [Print.pas][Print][TPrint.CreateCollection$qqrv][4274]
10A2773 [Print.pas][Print][TPrint.CreateItem$qqrv][3031]
The block is currently used for an object of class: TList
The allocation number is: 53883
Current memory dump of 256 bytes starting at pointer address 7EBA5360:
48 FA 49 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 7C C4 2D 79 00 00 00 00 E0 4B BA 7E
00 00 00 00 00 00 00 00 9C CD 41 00 00 00 00 00 7C D2 00 00 D2 75 40 00 AF AB 40 00 D6 B3 40 00
1A 72 11 01 29 AD 40 00 F8 57 11 01 40 D8 D1 00 0D A7 F3 00 58 B6 F3 00 CA 4C 0A 01 73 27 0A 01
58 05 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20 AD 40 00 B8 AB 40 00 D1 57 11 01 F4 1B 0B 01 22 4D 0A 01 87 27 0A 01 0A 48 11 01 52 6E 11 01
H  ú  I  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  |  Ä  -  y  .  .  .  .  à  K  º  ~
.  .  .  .  .  .  .  .  œ  Í  A  .  .  .  .  .  |  Ò  .  .  Ò  u  @  .  ¯  «  @  .  Ö  ³  @  .
.  r  .  .  )  ­  @  .  ø  W  .  .  @  Ø  Ñ  .  .  §  ó  .  X  ¶  ó  .  Ê  L  .  .  s  '  .  .
X  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  x  ï  ï  †
<  -  .  .  À  F  ¼  ~  .  .  .  .  .  .  .  .  .  .  .  .  ‡  .  .  y  .  .  .  .  .  Q  º  ~
.  .  .  .  .  .  .  .  .  .  .  .  .  .  .  .  €  Ò  .  .  Ò  u  @  .  ¯  «  @  .  Ö  ³  @  .
­  @  .  ¸  «  @  .  Ñ  W  .  .  ô  .  .  .  "  M  .  .  ‡  '  .  .  .  H  .  .  R  n  .  .

泄漏似乎是由TList引起的,但我释放了每个TList。TList.Free还不够吗?

那么,如何读取 FastMM 日志?

最相关的部分是声明"当时的堆栈跟踪(返回地址)是:"的部分,其中 您将看到如下所示的列表。这就是所谓的堆栈跟踪。

堆栈跟踪显示程序的执行路径;哪个函数调用了哪个函数。

首先,很高兴知道对于日志中的每一行:

  • 第一个数字是该函数所在的内存地址(EXE 文件)
  • 括号中的最后一个数字是函数所在的源代码行号(PAS 文件)。

我们从底部开始阅读。

因此,我们可以看到所有这些都是从 Print.pas 单元开始的。对象的创建项方法 称为CreateCollection,它试图创建一个新对象。 最后(见上行)我们最终进入 TObject 的构造函数。该构造器是一个类方法:ClassCreate。 TObject.NewInstance 意味着 TObject 实际上是在创建。在那里,构造函数通过 GetMem 为对象分配了一些内存(通常)。

现在,到目前为止,没有发生任何错误。 我们在创建对象时分配了一些内存。没什么大不了的。 当程序员忘记释放该内存时,就会发生错误。 换句话说,我们创建了一个对象,但我们从未释放它。

无论如何,日志似乎有点奇怪,因为堆栈跟踪显示正在创建一些项目.
所以我们需要进入源代码并检查我们调用 TPrint.CreateItem 的所有位置。 如果你只有一个地方调用TPrint.CreateItem,那么你很幸运。你只需要检查这个新项目应该在哪里发布,因为它显然不是。 如果你只有一个地方调用TPrint.CreateItem,那么你是相当幸运的。你必须检查每个地方。


但是,日志抱怨 TList 本身没有发布(不抱怨其项目) - 也许日志不完整?

该块当前用于类的对象:TList

所以,释放那个TList应该就足够了。 我想,这里发生的事情是一些外部代码控制了项目并释放了它们,而 TList 本身没有被释放。

>请记住,如果您没有看到详细的堆栈跟踪,则意味着您需要:
  • 禁用编译器优化
  • 在同一页面中,启用堆栈帧
  • 启用地图文件

如果创建对象并将其引用保存到 TList,则必须在释放 TList 之前释放它们。

for I := 0 to aList.Count-1 do
anObjectType(aList[I]).Free;

如果要自动释放对象,请将TObjectList与参数集一起使用OwnsObjectsTObjectList在销毁时释放其所有对象的内存。

相关内容

  • 没有找到相关文章

最新更新