【发布时间】:2014-03-17 17:55:17
【问题描述】:
我正在寻找一个 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% 效率
因此,根据 Process Explorer,FastMM4 似乎不知道程序消耗的额外内存。
我使用的是今天从 SourceForge 下载的 FastMM4 版本 4.991。测试程序在DEBUG模式下运行,定义如下:
完全调试模式
UseCustomFixedSizeMoveRoutines
使用自定义变量大小移动例程
无调试信息
ASMVersion
DetectMMOperationsAfterUninstall
RawStackTraces
LogErrorsToFile
LogMemoryLeakDetailToFile
AlwaysAllocateTopDown
抑制FreeMemErrorsInsideException
启用内存泄漏报告
HideExpectedLeaksRegisteredByPointer
RequireDebuggerPresenceForLeakReporting
启用MMX
强制MMX 启用BackwardCompatibleMMSharing
使用输出调试字符串
问题:
这些功能是否存在任何已知问题?我是否没有正确使用它们,是否不打算在一个调试会话中多次调用它们?有没有办法再次释放该内存?
【问题讨论】:
-
我在源代码中看不到任何会导致此类问题的内容。您能否也列出您已设置的定义?
-
@Graymatter:我一回到办公室就在周三的测试系统前会这样做 - 抱歉。
-
如果内存被随机覆盖,使用gFlags 可能会更好?!您没有指定内存覆盖是否会导致异常。如果他们不这样做,恐怕 gFlags 不是一个选择。如果他们这样做,那么值得一试。我很好奇你是怎么知道内存被覆盖的?
-
@Graymatter:我已将信息添加到我的问题中。
-
@LievenKeersmaekers:内存覆盖很容易注意到,它们经常修改在 UI 中可见或写入数据文件的字符串。如果字符串数据被覆盖,这是相对良性的,但是当字符串的引用计数或长度被修改时,程序迟早会出现异常。我还无法查明这些覆盖的来源。字符串数据应该是不可变的,但我无法在写入这些内存位置时设置硬件断点。