【问题标题】:Strategy or tools to find "non-leak" memory usage problems in Delphi?在 Delphi 中查找“非泄漏”内存使用问题的策略或工具?
【发布时间】:2011-10-18 11:09:29
【问题描述】:

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

根据 FastMM4 和 EurekaLog,没有内存泄漏(28 字节除外),所以我假设应用程序关闭时所有内存都被释放。

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

【问题讨论】:

    标签: delphi memory-management delphi-2006


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

    注意,如果某些 DLL 占用了内存,那么您可能无法使用 (3) 看到她的内存使用情况。使用 (2)。

    分析内存使用情况和应用程序执行的任务,您可能会发现导致内存使用量增加的原因。

    【讨论】:

    • MemProof(v.0.948,不确定这是最后一个)仍在 Torry 的:torry.net/authorsmore.php?id=1229
    • 问题是这是服务器类型的应用程序,所以很难确定单个动作。
    • @Harriv GetMemoryManagerUsageSummary 解决方案正是您所需要的。我在一个多线程服务中使用了它,它至少指向了疯狂的内存项的大小。
    • 对于多线程应用程序,跟踪功能是必须的。
    • @mj2008:能否简要解释一下您是如何使用 GetMemoryManagerUsageSummary 的?
    【解决方案2】:

    自 2012 年 9 月以来,有一种非常简单舒适的方法可以找到这种类型的“仅运行时”内存泄漏。

    FastMM4991 引入了一种新方法,LogMemoryManagerStateToFile

    添加了 LogMemoryManagerStateToFile 调用。此调用记录了以下内容的摘要 内存管理器状态到文件:总分配的内存,开销, 效率,以及按类和字符串类型分配的内存。 此调用可能有助于捕获不一定泄漏的对象,但 逗留的时间比他们应该的要长。

    要在运行时发现泄漏,您只需要这些步骤

    1. 将调用添加到LogMemoryManagerStateToFile('memory.log', '') 的位置,以便每隔一段时间调用它
    2. 运行应用程序
    3. 使用tail程序(例如BareTail)打开日志文件,当文件内容发生变化时会自动刷新
    4. 查看文件的第一行,它们将包含占用内存最多的内存分配
    5. 如果您发现某个类或内存类型的实例数量不断增加,这可能是您泄漏的原因

    【讨论】:

    • 如果页面文件在每次执行后持续增长但memory.log 显示没有任何持续增长,您能帮忙评论一下应该怎么做吗?
    【解决方案3】:

    AQTime(一个非常昂贵的商业工具)可以报告您的内存使用情况,直至分配每个对象的源代码行。在非常大的内存使用情况下,您可能需要 AQTime 功能来显示每个对象的对象数量和大小(总和单个实例大小)。 AQTime 非常适合我,从 Delphi 7 开始,以及所有更高版本,包括您的版本 (2006) 和最新版本(XE 和 XE2)。

    随着程序内存使用量的增长,AQTime 可用于抓取运行时堆的“快照”,您可以使用它来了解您的应用程序的内存使用情况;正在创建什么,每个对象有多少存在。即使不存在泄漏,根据应用程序创建和管理的对象了解应用程序的运行时行为也非常重要,而 AQTime 是我所知道的 Delphi 用户最强大的工具。

    如果您愿意升级到 Delphi XE/XE2,您可能已经包含了 AQTime 的精简版,如果是,请查看。如果没有,我建议您尝试他们的演示。我不知道有任何免费或开源替代品可以提供相同的功能。

    可以通过编写大量跟踪消息或使用 FastMM 完整调试模式手动拼凑较小的功能。如果您可以将内存使用情况的完整转储写入一个非常大的文件,您也许可以编写一些工具来解析并创建摘要。在这种情况下,我对 FastMM 的问题是,您将被详细信息淹没,而无法准确提取有助于您了解情况的摘要信息。因此,您可以尝试编写自己的工具来总结内存使用情况。在一个应用程序中,我使用了一系列我知道会占用大量内存的组件,我在我的应用程序中编写了一个对话框,显示这些大型内存数据对象的当前内存使用情况。

    【讨论】:

    • 请注意:Denomo 无法在 D2006 下编译,修复后会损坏某些内容,导致应用程序无法使用。
    【解决方案4】:

    你有没有想过导致 IDE 的泄漏......它是如此巨大!!!

    在我的情况下(2GB 内存)我会做下一个... 1.打开IDE 2.让它最小化近六个小时 3. 了解物理内存的使用情况

    结果: 虽然 IDE 已打开(请记住,我还进行了最小化的测试)它正在获得越来越多的 RAM ......直到没有更多的 ram 空闲。 它获得所有 2GB RAM + 所有 Pagefile 硬盘空间(我将其配置为 4GB) 在不到六个小时内(在 IDE 上什么都不做),它会尝试使用超过 6GB 的空间。

    这被称为 IDE 造成的内存泄漏...我不在 IDE 上键入任何字母,不编译任何内容,甚至不打开任何项目...只需打开 IDE 并将其最小化...离开计算机上大约六个小时没有做任何事情,IDE 正在消耗 6GB 的内存。

    当然,在那之后,IDE 以 SystemOutOfMemory 的烦人消息开始......我必须杀死它......然后所有 6GB 都被释放!!!

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

    请注意我已经应用了所有补丁,我还测试了没有应用每个补丁/修补程序等...

    我得到的最好的结果是禁用工具上的一些选项,比如下划线错误代码的选项,等等......那么为什么该选项有任何影响......我没有在 IDE 上输入任何东西(在测试)...如果我禁用它,内存泄漏会减少很多...

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

    看来短期内不会有解决方案了!!!

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

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

    【讨论】:

      猜你喜欢
      • 2010-09-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-15
      • 1970-01-01
      • 2012-08-09
      • 1970-01-01
      相关资源
      最近更新 更多