什么是私人字节,虚拟字节,工作集?

我正在尝试使用perfmon窗口实用程序来调试过程中的内存泄漏。

这就是perfmon如何解释术语:

工作集是此进程的工作集的当前大小(以字节为单位)。 工作集是进程中线程最近触及的一组内存页面。 如果计算机中的可用内存超过阈值,即使不在使用中,页面也会留在进程的工作集中。 当空闲内存低于阈值时,页面将从工作集中删除。 如果需要的话,在离开主存之前,他们将被软件故障切换回工作集。

虚拟字节是进程正在使用的虚拟地址空间的当前大小(以字节为单位)。 使用虚拟地址空间不一定意味着相应地使用磁盘或主内存页面。 虚拟空间是有限的,这个过程会限制它加载库的能力。

专用字节是当前的大小,以字节为单位,该进程分配的内存不能与其他进程共享。

这些是我有的问题:

是我应该测量的私人字节,以确定这个过程是否有任何泄漏,因为它不涉及任何共享库,如果发生任何泄漏,将来自过程本身?

该进程消耗的内存总量是多少? 它是虚拟字节还是虚拟字节和工作集的总和?

私人字节,工作集和虚拟字节之间有任何关系吗?

还有没有其他工具可以更好地了解内存使用情况?

这个问题的简短答案是, 这些值中没有一个是可执行程序正在使用多少内存的可靠指标,它们都不适合用于调试内存泄漏。

专用字节是指进程可执行文件所要求的内存量 – 不一定是实际使用的数量。 他们是“私人的”,因为他们(通常)排除内存映射文件(即共享的DLL)。 但是 – 这里有个问题 – 它们不一定排除这些文件分配的内存。 无法判断私有字节的更改是由于可执行文件本身还是由于链接的库引起的。 专用字节也不是唯一的物理内存; 他们可以分页到磁盘或待机页面列表(即不再使用,但也没有分页)。

工作集是指进程使用的总物理内存(RAM)。 但是,与专用字节不同,这也包括内存映射文件和各种其他资源,所以它比专用字节更不精确。 这与在任务管理器的“内存使用情况”中报告的值相同,并且近年来一直是无穷无尽的混乱的来源。 工作集中的内存是“物理”的,因为它可以在没有页面错误的情况下被处理; 但是,备用页面列表仍然在物理上位于内存中,但不在工作集中报告,这就是为什么在最小化应用程序时,您可能会看到“内存使用情况”突然下降的原因。

虚拟字节是整个进程占用的总虚拟地址空间 。 这就像工作集,它包含内存映射文件(共享DLL),但它也包括备用列表中的数据和已经被分页出来的数据,并且位于某个磁盘上的页面文件中。 在系统负载较重的情况下,每个进程使用的虚拟字节总数将比机器实际拥有的内存大得多。

所以关系是:

  • 私人字节是您的应用程序实际分配的内容,但包括页面文件的使用情况;
  • 工作集是非分页的专用字节加内存映射文件;
  • 虚拟字节是工作集加分页的专用字节和备用列表。

这里还有一个问题。 就像共享库可以在您的应用程序模块内分配内存一样,导致您的应用程序的专用字节中报告的潜在误报, 您的应用程序也可能最终在共享模块内分配内存,从而导致错误的否定 。 这意味着实际上您的应用程序可能会有内存泄漏,而这些内存泄漏永远不会显示在私有字节中。 不太可能,但可能。

专用字节是您的可执行程序正在使用的内存量的合理近似值 ,可用于帮助缩小可能的内存泄漏候选列表的范围; 如果你看到这个数字在不断增长,不断增长,你会想要检查这个过程是否有漏洞。 然而,这不能证明有或没有泄漏。

在Windows中检测/纠正内存泄漏的最有效工具之一实际上是Visual Studio (链接转到使用VS进行内存泄漏的页面,而不是产品页面)。 理性净化是另一种可能性。 微软在这方面也有一个更一般的最佳实践文档 。 在上一个问题中列出了更多的工具。

我希望这清除了一些东西了! 跟踪内存泄漏是调试中最难的事情之一。 祝你好运。

你不应该尝试使用perfmon,任务管理器或类似的工具来确定内存泄漏。 他们很好地识别趋势,但没有其他的东西。 他们报告的绝对数字过于模糊,并且对于诸如内存泄漏检测之类的特定任务是有用的。

以前对这个问题的回答给出了各种类型的很好的解释。

你问一个工具推荐:我推荐Memory Validator。 能够监视数十亿内存分配的应用程序。

http://www.softwareverify.com/cpp/memory/index.html

免责声明:我设计了Memory Validator。

这里有一个有趣的讨论: http : //social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/我对这个线程的理解是释放小的分配是没有反映在私人字节或工作集。

长话短说:

如果我打电话

p=malloc(1000); free(p); 

那么私人字节仅反映分配,而不是分配。

如果我打电话

 p=malloc(>512k); free(p); 

那么专用字节正确地反映了分配和解除分配。

性能计数器的定义从一开始就被打破了,由于某种原因似乎太难纠正了。

Windows内存管理的一个很好的概述可以在MSDN上的视频“ 内存管理之谜 ”中找到:它涵盖了比追踪内存泄漏(比如工作集管理)更多的主题,但是在相关主题中提供了足够的细节。


为了给你一个关于perfmon计数器描述的问题,下面是关于MSDN上的“ Private Bytes Performance Counter – Beware!专用字节的内幕:

问:什么时候私人字节不是私人字节?

答:当它不是常驻的时候。

Private Bytes计数器报告进程的提交费用。 也就是说,交换文件中已分配的空间量用于保存私有内存的内容。 注意:由于可能与保留状态下未提交的虚拟内存混淆,我避免使用“保留”一词。


从MSDN上的“ 性能规划

3.3私人字节

3.3.1说明

私有内存,被定义为为其他进程无法共享的进程分配的内存。 当在一台机器上执行多个此类进程时,此内存比共享内存更昂贵。 (传统)非托管dll中的私有内存通常由C ++静态构成,占dll总工作集的5%。