我正试图在我的.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]
的2D锯齿状数组时,任务管理器会报告提高内存使用量。
答案 0 :(得分:6)
它们是两种完全不同的记忆措施。工作集是程序使用的RAM量。它是一个不断变化的数字,受其他进程需要多少RAM的影响。您不能用完RAM,Windows可以通过将映射页面交换到页面文件来使RAM可用。
专用字节数是指程序使用的虚拟内存量,不与任何其他进程共享。在32位计算机上,您可以使用2 GB的虚拟内存。它需要在代码和数据之间共享。当可寻址的虚拟内存量中没有足够的空间来满足所请求的分配时,您将获得OOM。是的,这是更准确的数字。
一次要求100兆字节是有风险的。虚拟内存空间可能会碎片化,过了一段时间后,可能仍有大量的免费虚拟内存,但不是一个足以容纳100兆字节的漏洞。锯齿状数组解决了这个问题,因为它是一个数组数组,所需的块更小,所以可以很容易地适应任何剩下的孔。
64位操作系统完全解决了这个问题。您的程序有许多千兆字节的可用地址空间,实际上仅受页面文件的最大大小限制。你根本无法用完大洞。
答案 1 :(得分:1)
如果您想要追踪内存泄漏,并且通过阅读代码找不到它,那么您可能需要一个专为此工作而设计的真实工具。
任务管理器和Process Explorer都不是用于调试内存泄漏的适当工具 - 您需要一些能够告诉您分配未返回内存的位置。