【问题标题】:Task Manager disagrees with Process Explorer?任务管理器不同意 Process Explorer?
【发布时间】:2011-06-21 14:29:16
【问题描述】:

我正在尝试查找我的 .NET 应用程序中的内存泄漏。 Windows 任务管理器报告内存使用量保持不变,而Process Explorer 报告内存使用量正在增加。

在任务管理器中,我正在查看唯一的内存列“内存(私有工作集)”。在 Process Explorer 中,我正在查看“Private bytes”列,因为它正在上升,而“Working set”下的值不是。

现在,当然 Process Explorer 是正确的,因为在多次分配后,我的应用程序崩溃并出现 Out of memory 异常。问题是,为什么任务管理器会误报应用程序的内存使用情况?不仅如此,它还误报了全局系统可用内存(性能选项卡中的图表保持不变)。

不需要我的代码,但这里是为了完整性。它显示了一个包含大数组的空窗口。当按下任意键时,窗口关闭并打开一个新窗口,其中包含一个新数组。旧窗口已经泄露,可能是由于 qt4dotnet GUI 库中的错误。

using System;
using com.trolltech.qt.gui;

namespace LeakTest
{
    class Test : QWidget
    {
        public byte[] Data = new byte[1000 * 1000 * 100];

        public Test()
        {
            show();
            GC.Collect(); // so measurements are more accurate
        }

        protected override void keyPressEvent(QKeyEvent arg__1)
        {
            disposeLater();
            new Test();
        }

        [STAThread]
        static void Main(string[] args)
        {
            QApplication.initialize(args);

            new Test();

            QApplication.exec();
        }
    }
}

操作系统:Windows 7

有趣的提示:当我将“数据”设为二维锯齿状数组 [1000 * 1000 * 100][1] 时,任务管理器确实报告内存使用量增加。

【问题讨论】:

  • 我强烈反对使用任务管理器/进程资源管理器来查找 .NET 内存泄漏。通常,我使用ANTS Memory Profiler,即使使用这样一个专门的工具,也很难找到泄漏。如果我只是使用任务管理器,我将没有机会在过去找到我的漏洞。
  • 从未使用过的页面不需要任何支持,因为它们可以在第一次访问时被 0ed。所以它们算作私有字节,但不需要任何 RAM,也不属于工作集。
  • @CodeInChaos:啊,这解释了很多。

标签: .net windows memory-leaks taskmanager process-explorer


【解决方案1】:

它们是两种完全不同的记忆量度。工作集是您的程序使用的 RAM 量。它是一个不断变化的数字,受其他进程需要多少 RAM 的影响。您不能用完 RAM,Windows 通过将映射页面交换到页面文件来为您提供 RAM。

私有字节是您的程序使用的不与任何其他进程共享的虚拟内存量。在 32 位机器上,您有 2 GB 的可用虚拟内存。它需要在代码和数据之间共享。当可寻址的虚拟内存量中没有足够的空间来满足请求的分配时,您会得到 OOM。是的,这是更准确的数字。

一次请求 100 兆字节是有风险的。虚拟内存空间可能会变得碎片化,一段时间后可能仍然有大量可用的虚拟内存,但没有大到足以容纳 100 兆字节的空洞。锯齿状数组解决了这个问题,因为它是一个数组数组,所需的块要小得多,因此可以轻松容纳剩下的任何孔。

64 位操作系统完全解决了这个问题。您的程序有 许多 GB 的可用地址空间,实际上仅受页面文件的最大大小限制。你根本无法用完大洞。

【讨论】:

    【解决方案2】:

    如果您想追踪内存泄漏,但您无法通过阅读代码找到它,那么您可能需要一个专为这项工作设计的真正工具。

    任务管理器和进程资源管理器都不是调试内存泄漏的合适工具——您需要一些能够告诉您分配未返回内存的位置的工具。

    【讨论】:

    • @Uwe 确实!当然,在像 .net 这样的 GC 系统中,即使使用了出色的工具,也很难追踪到它们。
    • @Uwe Keim:是的,我实际上也在使用 dotTrace Memory Profiler,但我无法弄清楚它告诉我什么(它变得非常复杂,因为我使用 Java 绑定通过 .NET 的 C++ 库)。所以我试图在没有探查器的情况下尽可能多地理解。我偶然发现了这种无法解释的行为,所以我发布了这个问题。我可能会向分析器发布另一个问题。
    • @Stefan 试试 ANTS 内存分析器;这是迄今为止我用过的最好的工具,也许它也可以帮助你。
    猜你喜欢
    • 1970-01-01
    • 2020-07-01
    • 1970-01-01
    • 2016-06-07
    • 2022-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多