在Delphi中查找“非泄漏”内存使用问题的策略或工具是什么?

10

在服务器更新后,一个旧应用程序开始大量消耗内存。内存使用似乎会无限上升,直到程序挂起。

根据FastMM4和EurekaLog的分析,除了28字节外,没有内存泄漏,因此我假设在应用程序关闭时所有内存都被释放。

有没有适合跟踪这种内存问题的工具或策略?

4个回答

9
自2012年9月以来,有一种非常简单且方便的方法可以查找此类型的“仅运行时”内存泄漏。
FastMM4991引入了一种新方法,即LogMemoryManagerStateToFile

添加了LogMemoryManagerStateToFile调用。此调用将内存管理器状态的摘要记录到文件中:分配的总内存、开销、效率以及按类和字符串类型分配的内存的细分。此调用可能对捕获不一定泄漏但存在时间比应该长的对象很有用。

为了在运行时发现泄漏,您只需要执行以下步骤:
  1. 在会定期调用的位置添加调用LogMemoryManagerStateToFile('memory.log', '')
  2. 运行应用程序
  3. 使用“tail”程序(例如打开Notepad++并切换到尾随模式)打开日志文件,该程序会在文件内容更改时自动刷新
  4. 查看文件的前几行,其中将包含占用最大内存量的内存分配
  5. 如果您看到某个类或内存类型的实例数量不断增长,则可能是泄漏的原因

你能否帮忙评论一下,如果每次执行后页面文件持续增长,但是 memory.log 显示没有不断增长的内容,应该做些什么? - SOUser

8
  1. 内存消耗增长是一个应用程序问题,而不是 FastMM4 或 EurekaLog 可以发现的 bug。从他们的角度来看,应用程序只是正确地使用了内存。
  2. 使用 AQTime、MemProof(很难找到,D7 是最后支持的版本 (?))、SleuthQA 或类似的内存分析工具,您可以实时跟踪应用程序外部的内存使用情况。
  3. 使用 FastMM4、GetMemoryManagerState / GetMemoryManagerUsageSummary,您可以从应用程序中跟踪内存使用情况。将这些信息输出到跟踪文件中,并在运行后进行分析。或者编写一个简单的包装函数来调用上述某个过程,该函数将返回当前内存使用情况。然后从 IDE Debugger Evalute / Modify 调用它,将其添加到 Watches 中或调用 OutputDebugString,查看当前内存使用情况。

请注意,如果某个 DLL 消耗了内存,则您可能无法使用 (3) 来查看其内存使用情况。请使用 (2)。

通过分析应用程序的内存使用情况和执行的任务,您可能会发现是什么导致了内存使用量的增加。


2
MemProof(v.0.948,不确定是否为最新版本)仍然在Torry上:http://www.torry.net/authorsmore.php?id=1229 - ain
问题在于这是服务器类型的应用程序,因此很难确定单个操作。 - Harriv
@Harriv 你需要的是GetMemoryManagerUsageSummary解决方案。我在一个多线程服务中使用了它,至少能指出那些内存项的大小变得非常大。 - mj2008
对于多线程应用程序来说,跟踪能力是必不可少的。 - da-soft
@mj2008:你能简要解释一下你如何使用GetMemoryManagerUsageSummary吗? - Harriv
@Harriv我不记得具体细节了,但我修改了使用窗口输出的样例,使其能够周期性地保存到日志文件中。这给了我随着时间推移的详细信息。我还记得在madExcept中使用了一些代码来提供给我每个线程的内存使用情况,但可能是CPU使用情况 - 不确定!不幸的是,那是一段时间以前的事情了。你提到这是一个服务器应用程序,但如果它不是一个服务,那么AQTime可能是最好的选择,因为它可以看到完整的堆栈跟踪。如果它是一个服务,请创建一个创建服务模块的应用程序并使用它。 - mj2008

2
AQTime是一款商业工具,价格相当昂贵,它可以报告您的内存使用情况,直到分配每个对象的源代码行。对于非常大的内存使用场景,您可能需要AQTime功能,以显示每个对象的对象数和大小(总大小加上每个实例的大小)。从Delphi 7开始,AQTime对我来说运作得非常好,包括您的版本(2006)和最新版本(XE和XE2)。随着程序内存使用量的增长,可以使用AQTime抓取运行时堆的“快照”,以了解应用程序的内存使用情况;正在创建什么以及每个对象的数量。即使没有泄漏存在,理解应用程序在创建和管理对象方面的运行时行为非常重要,而AQTime是我所知道的Delphi用户最强大的工具。
如果您愿意升级到Delphi XE / XE2,则可能已经包含了AQTime的轻量级版本,如果是这样,请查看它。如果没有,建议尝试他们的演示版。我不知道有任何免费或开源的替代品可以提供相同的功能。
较少的功能可以通过编写大量跟踪消息或使用FastMM全调试模式来手动组合。如果您可以将完整的内存使用情况转储到一个非常大的文件中,您可能可以编写一些工具来解析并创建摘要。我在这种情况下对FastMM的问题在于,您将被淹没在详细信息中,而无法提取恰好帮助您了解情况的摘要信息。因此,您可以尝试编写自己的工具来总结内存使用情况。在我使用一系列组件的一个应用程序中,我知道它们将使用大量内存时,我编写了一个对话框到我的应用程序中,显示这些大内存数据块对象的当前内存使用情况。

请注意:Denomo在D2006下无法编译,即使修复后,也会破坏某些内容,导致应用程序无法使用。 - Harriv

0

你有没有想过那个导致IDE泄漏的问题...它太大了!!!

在我的情况下(2GB的RAM),我做了以下操作... 1. 打开IDE 2. 最小化它近六个小时 3. 观察物理内存的使用情况

结果: 当IDE打开时(记住我也测试了最小化它的情况),它会越来越多地占用RAM...直到没有更多的可用RAM。 它占用了所有2GB的RAM + 所有页面文件硬盘空间(我将其配置为最大4GB) 不到六个小时(在IDE上什么都不做)它就试图使用超过6GB。

这就是由IDE引起的内存泄漏...我没有在IDE上输入任何字母,没有编译任何东西,甚至没有打开任何项目...只是打开IDE并将其最小化...让计算机保持不动约六个小时,IDE就会消耗6GB的内存。

当然,在此之后,IDE开始出现烦人的SystemOutOfMemory消息...我必须杀掉它...然后所有的6GB都被释放了!!!

这个问题什么时候才能得到解决?

请注意,我已经应用了所有的补丁,我也测试了不应用每个补丁/热修复程序等的情况...

我最好的解决方案是禁用工具中的某些选项,比如下划线错误代码等... 所以为什么这个选项会有影响... 我没有在 IDE(测试时)输入任何内容... 如果我禁用了它,内存泄漏就会大大减少...

当然,如果我使用 IDE (在打开的项目上编写代码)而不进行编译/运行... 事情会变得更加糟糕... 内存泄漏会在不到一个小时内达到6GB,有时在复制/粘贴源代码15分钟后就会发生。

看起来短时间内不会有解决方案!!!

所以我找到了下一个完美的解决方案: -每15分钟或更短时间关闭 IDE 并重新打开它

丑陋的解决方案,我知道... 但它有效!!!


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