【问题标题】:My program never releases the memory back. Why?我的程序永远不会释放内存。为什么?
【发布时间】:2011-05-26 17:25:01
【问题描述】:

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

注意:我使用任务管理器中的 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)

【问题讨论】:

标签: delphi


【解决方案1】:

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

【讨论】:

  • > 因此,即使在您释放所有资源后,分配的内存也会有所增加 - - - - 我知道这一点。但没想到数量这么多。我会试试 MemProof。编辑:实际上,如果它为每个最近关闭的窗口保留大约 1MB 的 RAM,那么这是有道理的。
  • 如果你最小化你的程序,你的应用程序的内存使用是否会突然下降?那么你的结论是基于错误的统计数据。
  • @Lars-我熟悉这种行为(自 Win XP 以来似乎就存在)。这是尝试的第一件事 :) 不幸的是,此应用程序不会发生这种情况。
【解决方案2】:

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

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


这是...\FastMM\Demos\Usage Tracker 目录中的FastMMUsageTracker.pas
使用该单元,然后在其中调用 ShowFastMMUsageTracker 函数。 您可以不时刷新该表单以查看您的内存消耗如何增长。 我放了一个FastMMUsageTrackerProject 示例on-line,包括一个FastMM4 的更新,它可以更轻松地检查和调试内存泄漏:

  • FastMMUsageTracker 单元中的表单现在可以调整大小,并且其中的控件以正确的方式锚定
  • 有一个新的FastMmBootstrapUnit 单元可以更轻松地调试特定的内存泄漏

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

注意:我即将在

上发布 FastMM 的更新

--杰罗恩

【讨论】:

  • >FastMM 单元显示具有当前内存使用情况的表单? - - - 我不知道这个单位。也许它只适用于 Delphi 2010?你能提示我一些名字,以便我可以在谷歌上搜索它吗?
  • 人们说 FastMM 不会失败:stackoverflow.com/questions/4477936/… 我想我同意他们的观点。
  • @Jeroen-谢谢。我将立即使用该装置。我已经对照 GlobalAlloc 检查了我的代码和 3rd 方库。我的项目中没有使用它。
【解决方案3】:

答案:

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

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

更新:

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

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

【讨论】:

    【解决方案4】:

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

    例如,当您关闭 MDI 子窗口时,您是对它们调用 Free 或 Release,还是只是让它们消失?如果它们被隐藏但没有被释放,它们仍然会在内存中。

    【讨论】:

    • 我释放了表格。如果仅隐藏子窗体,则 RAM 量不会从 500 降至 160MB。
    • 您确定表单仅适用于持有对它们正在显示的数据的引用的对象吗?可能不是表格无法释放内存。
    • @codeelegance。是的。另外,如果我未能释放某些对象(内存泄漏),FastMM 会立即向我扑来。
    • 正如 Mason 指出的,FastMM 只会在程序终止时抱怨。您在它仍在运行时询问了内存使用情况。只要对象在终止前被释放,FastMM 就不会出现问题。
    • >只要对象在终止前被释放,FastMM 不会有问题 - - - 同意你的观点!!这意味着(因为我的 FastMM 没有抱怨)我不会泄漏内存!这很好。问题是:FastMM 不释放内存是否健康???也许其他程序非常需要内存。
    【解决方案5】:

    如果您关闭 MDI 表单,它不会自动释放。使用 Action = caFree (google for that) 确保表单也被释放。

    【讨论】:

    • 我释放了表格(请参阅以前的答案)。
    猜你喜欢
    • 2023-04-01
    • 2015-06-14
    • 1970-01-01
    • 2021-08-08
    • 1970-01-01
    • 2021-06-28
    • 1970-01-01
    • 2020-01-06
    • 1970-01-01
    相关资源
    最近更新 更多