2011-02-04 87 views
3

我想追踪我的.NET应用程序中的内存泄漏。 Windows任务管理器报告内存使用率保持不变,而Process Explorer报告内存使用率在上升。任务管理器不同意Process Explorer?

在任务管理器中,我正在查看唯一的存储器列“Memory(Private working set)”。在进程资源管理器中,我正在查看“专用字节”列,因为它在提升,而“工作集”下的值不是。

现在,当然,Process Explorer是正确的,因为经过几次分配,我的应用程序崩溃了内存不足异常。问题是,为什么任务管理器误报应用程序的内存使用量?不仅如此,还会误报全局系统空闲内存(“性能”选项卡中的图形保持不变)。

我的代码不应该被需要,但这里是为了完整性。它显示一个空的窗口,包含一个大数组。当按下任意键时,窗口关闭,并打开一个新窗口,保存一个新阵列。旧窗口已泄漏,可能是由于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]的二维交错数组,任务管理器确实报告提高内存的使用情况。

+1

我会强烈反对使用任务管理器/进程资源管理器来查找.NET内存泄漏。通常情况下,我使用[ANTS Memory Profiler](http://www.red-gate.com/products/dotnet-development/ants-memory-profiler/),甚至使用这种专用工具,也很难找到泄漏。如果我刚刚使用了任务管理器,我就没有机会在过去找到我的泄漏。 – 2011-02-04 20:27:06

+1

从未使用过的页面不需要任何支持,因为它们只能在第一次访问时被删除。所以他们算作专用字节,但不需要任何RAM,不属于工作集。 – CodesInChaos 2011-02-04 20:29:31

回答

6

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

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

一次请求100兆字节是有风险的。虚拟内存空间可能会变得碎片化,过了一段时间后,仍然会有大量的免费虚拟内存,但不会有足够大的空洞来容纳100兆字节。锯齿阵列解决了这个问题,因为它是一个数组数组,所需的块更小,因此可以很容易地适应任何留下的孔。

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

1

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

无论是任务管理器还是Process Explorer都不是用于调试内存泄漏的适当工具 - 您希望能够告诉您在哪里分配未返回的内存。