调用FastMM4的LogAllocatedBlocksToFile()定期记录会占用内存空间吗?

3
我正在调试一个 Delphi 5 程序中的一个难以捉摸的内存问题,该问题导致内存在客户端随机被覆盖。尝试了很多方法但没有结果,现在我想使用 LogAllocatedBlocksToFile() 中的 FastMM4 输出来查找哪些对象在被覆盖区域之前立即被分配。程序使用定时器每30分钟将分配的块信息写入新文件。不幸的是,我的程序测试运行(DEBUG构建)在大约23小时后崩溃,并出现 EOutOfMemory 异常,根据 MadExcept 显示,已分配了1.83 GB 的内存。
从 SysInternals Process Explorer 图中看,每次调用 LogAllocatedBlocksToFile() 都会分配但未释放内存:
CPU 使用率图表中的红色峰是 LogAllocatedBlocksToFile() 的调用。我已经添加了对 LogMemoryManagerStateToFile() 的调用,紧接着发生最后一次峰值(私有字节从约183 MB 增加到约218 MB),数据如下:

55054K 已分配
47911K 开销
53% 效率

和这个:

55055K 已分配
47910K 开销
53% 效率

因此,FastMM4 似乎并不知道程序根据 Process Explorer 消耗的额外内存。
我使用的是从 SourceForge 下载的 FastMM4 版本4.991。测试程序在 DEBUG 模式下运行,并设置了以下宏定义:

FullDebugMode

UseCustomFixedSizeMoveRoutines
UseCustomVariableSizeMoveRoutines
NoDebugInfo
ASMVersion
DetectMMOperationsAfterUninstall
RawStackTraces
LogErrorsToFile
LogMemoryLeakDetailToFile
AlwaysAllocateTopDown
SuppressFreeMemErrorsInsideException
EnableMemoryLeakReporting
HideExpectedLeaksRegisteredByPointer
RequireDebuggerPresenceForLeakReporting
EnableMMX
ForceMMX EnableBackwardCompatibleMMSharing
UseOutputDebugString

问题: 这些功能是否存在已知问题?我是否没有正确使用它们,它们是否不适合在一个调试会话中多次调用?有没有办法释放那些内存?

2
我在源代码中没有看到任何可能导致这种问题的内容。你能否提供你所设置的宏定义列表? - Graymatter
@Graymatter:抱歉,我会在周三回到办公室,在测试系统前进行操作。届时会尽快处理。 - mghie
如果内存被随机覆盖,也许使用gFlags会更好?!您没有说明内存覆盖是否导致异常。如果没有,恐怕gFlags不是一个选项。如果有,那就值得一试。我很好奇您是如何知道首先内存被覆盖的? - Lieven Keersmaekers
@Graymatter:我已经在我的问题中添加了这些信息。 - mghie
@LievenKeersmaekers:内存覆盖很容易被注意到,它们经常修改在UI中可见或写入数据文件的字符串。如果字符串数据被覆盖,那么相对来说是比较温和的,但当字符串的引用计数或长度被修改时,程序中迟早会出现异常。我还没有能够确定这些覆盖的来源。字符串数据应该是不可变的,但我无法使硬件断点在写入这些内存位置时起作用。 - mghie
只是一个想法:LogAllocatedBlocksToFile()函数需要 FullDebugMode,但从源代码来看:a) Medium pool在 FullDebugMode 下不会被释放。 b) Small block pool在 FullDebugMode 下永远不会被释放。 可能与内存增长有关。 - pf1957
1个回答

7

简短版:

我追踪下来发现问题是由于支持库 FastMM_FullDebugMode.dll 版本不匹配导致的。

较旧的库可以与编译到可执行文件中的较新版本一起使用。似乎没有检查版本是否匹配。但是,模块在运行时实际上并不能很好地一起工作。

详细版:

该项目最初使用较旧版本的 FastMM4(版本 4.97),我已在此处检查了它,并与支持库一起提供(文件版本为 1.44.0.4,产品版本为 1.42)。

在尝试找出程序中的错误时,我将 FastMM4 升级到了版本 4.991。我还记得把新的支持库(文件版本为 1.61.0.6,产品版本为 1.60)复制到了构建目录中。然而,后来我可能将其从目录中删除了,或者一开始就将其复制到了错误的目录中,因为两个小时前,我检查了应用程序加载的模块,发现该应用程序从另一个目录中获取了旧版本的支持库,因为它并不在构建目录中。

自从将其复制到该目录并重新启动应用程序后,问题似乎已经解决了。当调用 LogAllocatedBlocksToFile() 时,内存使用情况不会增加。

也许这能帮助有所需要的人,所以我选择回答这个问题而不是删除它。

继续调试...


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