【问题标题】:Does FastMM detect all memory leaksFastMM 是否检测到所有内存泄漏
【发布时间】:2010-12-18 12:01:19
【问题描述】:

最近有人建议 (My program never releases the memory back. Why?) 我的程序泄漏了一些内存。我将 FastMM 设置为积极,当我关闭程序时它不会报告内存泄漏。

无论如何,我想知道是否存在 FastMM 未检测到的内存泄漏?

更新:我个人不使用 Win API 来分配内存。但我担心我使用的一些 3rd 方组件(不是很多)可能会使用它。你能告诉我 FastMM 无法拦截的所有可能的 API 调用吗?我将在我的代码中搜索它们。谢谢。


Delphi 7,Win 7 32 位
FastMM 4.97
我对接口不感兴趣。

【问题讨论】:

  • @Altar 我刚刚编写了一个应用程序,它分配一块内存,零填充它,然后释放它。 Process Explorer 报告的工作集统计信息会上升,然后返回到它们开始的级别。我正在使用带有 FastMM 的 vanilla D2010(当然这是默认设置)。
  • @Altar 我的问题是这个。为什么要找 FastMM 的问题,而不是先看自己的代码? FastMM 的使用非常广泛,我通常倾向于从认为它做得很好的信念开始。
  • @Altar 最后,您是否尝试过我发布到您的其他问题之一的基于 MSVCRT 的 MM?我敢打赌,它的性能与 FastMM 相同,这可能会说服您停止在那里寻找问题并查看您自己的代码。
  • @David 我不认为 Altar 声称 FastMM 是问题的根源。此外,一定是他的代码中的某些东西导致了问题,Altar 正在寻找一种方法来找出问题所在。
  • @Eugene 以前的问题调用了 FastMM,它有助于在以前线程的上下文中考虑这个线程

标签: delphi fastmm


【解决方案1】:

FastMM 是 Windows 内存管理之上的一层。显然,如果您(或某些组件或其他)使用 Windows API 分配内存,那么这种分配会绕过 FastMM,您将无法跟踪它。顺便说一句,Delphi 内存管理器自己使用该 API 来分配内存块。因此,如果您需要查看该级别的分配,FastMM 是不够的 - 您必须使用 AQTime 和类似工具(正如我在上一个问题中建议的那样)。

【讨论】:

  • 嗨,尤金。感谢您的确认。不,我不使用 Window API 来分配内存。
  • @Altar 你不知道,但也许某些组件可以。
  • 你是对的。我打算在我使用的第 3 方代码中搜索这种 API 调用。
【解决方案2】:

不,只有由 FastMM 分配的内存泄漏。

编辑: 也许答案看起来很复杂,但事实并非如此!如果有人检查 FastMM 的制作方法,则可以看到内存分配的每个指针都被推入(并在 FreeMem 中弹出)到一个堆栈中(有更多堆栈,取决于内存大小)所以在关闭应用程序结束时,FastMM 只检查堆栈,如果堆栈中有东西,如果是,则报告内存泄漏!

【讨论】:

  • 没有。它没有被包裹。我检查了分配 RAM 的 API 调用的代码(包括第 3 方代码),发现它没有它们。
【解决方案3】:

我从来不知道 FastMM 无法检测到内存泄漏。

【讨论】:

  • 很想听听关于否决票的解释。也许这里有人经历过 FastMM 未能检测到内存泄漏,很高兴与我们所有人分享这种经验。
  • 我没有投反对票,但我确实对其他 FastMM 神话有不好的体验。对于我的主要代码库,它比原来的 MM 慢得多。
  • @Marco 我对否决票没有意见,只是没有解释就没有人可以学习。我喜欢 SO 的地方在于我可以学习。至于 FastMM 性能,我只发现它是在线程争用严重的情况下出现的问题,这就是我使用 MSVCRT 的 malloc 的原因。旧的 Borland MM 的地址 >2GB 时发生了灾难性的失败,这对我来说是个阻碍。
  • @DavidHeffernan David 我记得看到您在 StackOverflow 上的回复之一是您发布的代码显示了您使用的非常简单的基本 MemoryManager。我找不到那个帖子。你还记得那是什么答案吗?非常感谢!!!很抱歉以这种方式与您联系。 :-)
  • @santiago stackoverflow.com/a/6072362/505088 这些天来,我现在在我的应用程序中使用了一个不同的 mm,旨在与 NUMA 很好地配合使用
【解决方案4】:

有几个可能的原因:(适用于任何内存管理器)

  • 您的主程序循环泄漏内存,但对关闭时释放的内存泄漏
    • 最简单的情况是记录到备忘录。备忘录越来越大,但在关机时被销毁。
  • 内存分配在 fastmm 的控制之外
    • 直接从窗口分配
    • 在 dll 等中分配的内存
  • 堆碎片。内存管理器保留分配的大块(例如,因为它仍然包含一小部分分配)。结果:应用程序不使用它,但它也没有发布到操作系统。运行时/内存管理器保留它。
    • fastmm 应该对这种现象更有弹性,但有疑问请尝试打印 heapmanager 信息以查看是否是这种情况。

【讨论】:

    【解决方案5】:

    已经有很多好的答案了,但还有一点没有提到......

    自从内存被释放后,大多数内存泄漏检测器都无法检测到许多“泄漏”,但是在它不再使用之后。例如,对象堆叠在 TObjectList 中。对象被放入对象列表中,但是在你使用完它们之后,你并没有释放它们。当对象列表也被销毁时,它们也会被销毁(例如,当应用程序关闭时,假设 OwnsObject=True)。由于对象实际上已被释放,因此对象不会“泄漏”,但仍会使您的应用程序随着时间的推移使用越来越多的内存。

    FastMM 不会报告这些,因为它只进行“全面运行”分析。要检测这些,您需要一个允许进行部分运行的内存泄漏检测器,即分析执行期间 A 点和 B 点之间“泄漏”的内容。 Eugene 提到的 AQTime 允许这种检查。但请注意,这需要进行一些分析,因为这会产生许多误报(几乎所有“realloc”操作都将被标记为泄漏)。

    【讨论】:

    • 实际上我将对象存储在 TObjectList 中,我确实理解您的观点,但它不适用于我的情况。我使用的对象链接到我创建的 MDI 子窗体(数百个)。 MDI 子级正在创建这些对象。当我释放 MDI 表单时,它们会释放所有对象。但除此之外,您的示例非常可靠。
    • Ken,这不是真正意义上的内存泄漏——你仍然拥有对每个对象的引用。如果您不再需要它们,那么坚持下去只是糟糕的编程。
    • 因此引用了“泄漏”。这些不是真正的泄漏,但它们具有与真正的泄漏完全相同的后果/症状。它们也经常被忽视,因为它们更难找到。而且这不一定是糟糕编程的结果,在许多情况下,只有完整的引用计数实现才能确保对象不会超过其有用性。有时,这种实现是被禁止的(因为系统架构师并不总是最聪明/知识最渊博的人。在不久的过去,我被禁止在系统上使用委托(即事件))
    【解决方案6】:

    FastMM 不会检测未通过 FastMM 的内存分配泄漏。

    这可能包括来自您使用的第 3 方库或 DLL 的 GlobalAlloc 调用。
    编辑:Microsoft 的 MSDN 有一个 nice list of memory allocation methods

    这实际上是我在my answer 中对您之前的 FastMM 问题提到的问题。

    您可以使用VMMap 之类的工具来跟踪 FastMM 无法检测到的内存泄漏。

    --杰罗恩

    【讨论】:

    • 我现在要搜索malloc和GlobalAlloc!有人知道我应该寻找其他类似的电话吗?
    • 我发现只有两个库在使用 GlobalAlloc:Melander Gif、Melander DragAndDrop。我没有在我的这个项目中使用它们。所以,FastMM 应该能够检测到所有的内存泄漏。
    • @Altar:几乎所有非 Delphi COM 对象和 C DLL 都将使用非 FastMM 内存分配。
    • 非常感谢 Jeroen 的这份名单。到目前为止,我已经检查了 malloc 和 GlobalAlloc 的代码。 - - - “几乎所有非 Delphi COM 对象和 C DLL 都将使用非 FastMM 内存分配”我知道,但我个人不使用 COM,也不使用外部 C DLL。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-07-16
    • 2012-04-29
    • 1970-01-01
    • 2012-01-22
    • 2021-09-01
    • 1970-01-01
    相关资源
    最近更新 更多