代码之家  ›  专栏  ›  技术社区  ›  Community wiki

我的程序永远不会释放内存。为什么?

  •  3
  • Community wiki  · 技术社区  · 2 年前

    我有一个MDI程序。当它启动时,它需要2-3MB的RAM。然后,在这个程序中,我创建了大约260个MDI子窗口(每个窗口都有一个TStringGrid、一个位图和一些其他控件),并显示一些数据。该应用程序需要大约500MB才能加载所有这些窗口。如果我手动关闭每个MDI子项,应用程序仍然使用160MB的RAM。为什么它没有返回到几MB的RAM?我应该担心这个吗?160MB对于一个只有1GB或RAM的系统来说,这是一个很大的数目!!

    注意:我使用任务管理器中的WORKING SET列来查看RAM统计信息。也许我需要一个更好的工具来读取RAM利用率。(专用工作集只是比工作集小一点)。

    这不是泄漏!
    当我关闭程序时,FastMM(设置为主动)表示没有内存泄漏。请参阅我的回答帖子,以获得其他证据,证明它不是泄漏。

    我发布东西
    很多人告诉我,关闭儿童窗口只会隐藏它。我知道这一点。我使用“Action:=caFree”来实际发布表单。每个表单都负责释放它所持有的控件。

    答复
    我发现FastMM对此负有责任。请参阅我在下面发布的答案。


    Delphi 7,Win 7 32位
    类似职位:
    Can memory be cleaned up?
    When to call SetProcessWorkingSetSize? (Convincing the memory manager to release the memory)

    5 回复  |  直到 8 年前
        1
  •  7
  •   Eugene Mayevski 'Callback    15 年前

    任务管理器不是检测内存泄漏的正确工具。Delphi会分配大块内存,并将其保留以备将来使用,因此即使在释放所有资源后,分配的内存也会有一定的增加。任何其他结果(以及更详细的答案)都只能通过使用专门的内存分析工具来获得。AQTime是第一个想到的,或者如果你能找到旧的但有用的MemProof,它会对你有很大帮助(MemProof是免费的,对于内存分析来说,它比AQTime更方便)。

        2
  •  4
  •   Jeroen Wiert Pluimers    15 年前

    FastMM很可能在应用程序终止时不会显示内存泄漏(例如,因为所有对象都是所拥有的TComponent,而所有者会释放它们)。
    但与此同时,在运行这些组件时,这些组件可能仍然存在,并且不会很快释放。

    您是否使用了显示当前内存使用情况的窗体的FastMM单元?

    <编辑>
    这是 FastMMUsageTracker.pas 在目录中 ...\FastMM\Demos\Usage Tracker
    使用该单元,然后调用 ShowFastMMUsageTracker 功能。 你可以每隔一段时间刷新一次该表单,看看你的内存消耗是如何增长的。 我放了一个 FastMMUsageTrackerProject 样品 on-line ,包括FastMM4的更新,使其更容易检查和调试内存泄漏:

    • 中的表单 FastMMUsageTracker 单元现在可以调整大小,其中的控件以正确的方式定位
    • 有一个新的 FastMmBootstrapUnit 使调试特定内存泄漏更容易的单元

    上周我手头有一个第三方DLL,它不是用Delphi编写的。
    DLL使用Windows GlobalAlloc调用发生内存泄漏,FastMM未跟踪这些调用。

    注意:我即将在上发布FastMM的更新

    --jeroen

        3
  •  4
  •   IceCold    7 年前

    答案:

    我刚刚从我的项目中删除了FastMM,在释放了所有这些子窗口后,程序返回到了几个MB。许多人可能会争辩说,这不是一种不当行为,FastMM这样做是为了进行某种古怪的内存优化。它们可能是真的。然而,它可能对我的应用程序有好处,但对其他正在运行的应用程序可能没有好处。

    所以,至少我们知道是谁造成了这种情况。我担心了一整天,可能程序正在像一个旧水桶一样泄漏RAM。我现在松了一口气。

    更新:

    为了确认这种行为是由FastMM生成的(正如Barry Kelly所建议的),我创建了第二个程序,该程序分配了大量RAM。一旦Windows的RAM用完,我的程序内存利用率就恢复到原来的值。
    (注意:我并不是说FastMM有漏洞!)

    我的程序没有泄漏。问题解决了。

        4
  •  0
  •   Mason Wheeler    15 年前

    FastMM的内存泄漏跟踪的主要限制是它只能在关闭程序时运行。这可能是因为你仍然持有对对象或其他数据的引用,这些数据在你关闭程序时会被清除,但在那之前一直存在。

    例如,当您关闭MDI子窗口时,是对它们调用“自由”或“释放”,还是只是让它们消失?如果它们被隐藏但没有被释放,它们仍将留在记忆中。

        5
  •  0
  •   Birger    15 年前

    如果关闭MDI窗体,它不会自动释放。使用Action=caFree(谷歌搜索)来确保表单也被释放。