什么是私有字节、虚拟字节、工作集?

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

perfmon是这样解释这些术语的:

工作集是这个进程的工作集的当前大小,单位是字节。工作集是进程中线程最近接触的内存页的集合。如果计算机中的空闲内存超过阈值,则即使没有使用页,页也会留在进程的工作集中。当空闲内存低于阈值时,将从工作集中删除页面。如果需要它们,它们将在离开主存之前被软故障恢复到工作集。

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

私有字节是当前进程分配的不能与其他进程共享的内存大小(以字节为单位)。

以下是我的问题:

它是私有字节,我应该衡量,以确定如果进程有任何泄漏,因为它不涉及任何共享库和任何泄漏,如果发生,将来自进程本身?

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

私有字节、工作集和虚拟字节之间有关系吗?

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

345020 次浏览

这个问题的简短答案是这些值都不是可执行文件实际使用多少内存的可靠指示器,也都不适合调试内存泄漏。

私有字节指的是进程可执行文件拥有的内存数量要求 -不一定是实际使用。它们是“私有的”,因为它们(通常)排除内存映射文件(即共享dll)。但是——这里有个问题——它们并不一定排除内存由这些文件分配。没有办法判断私有字节的变化是由于可执行文件本身,还是由于链接库。私有字节也是独占物理内存;它们可以分页到磁盘,也可以分页到备用页列表中(即不再使用,但也没有分页)。

工作集指进程使用的物理内存(RAM)总量。然而,与私有字节不同的是,它还包括内存映射文件和各种其他资源,因此它的测量甚至不如私有字节准确。这与任务管理器的“Mem Usage”中报告的值相同,并且近年来一直是无数困惑的来源。工作集中的内存是“物理的”,因为它可以在没有页面错误的情况下被寻址;然而,备用页列表仍然在物理内存中,但没有在工作集中报告,这就是为什么当你最小化一个应用程序时,你可能会看到“Mem Usage”突然下降。

虚拟字节是整个进程所占用的虚拟地址空间的总和。这类似于工作集,因为它包括内存映射文件(共享dll),但它还包括备用列表中的数据和已经换出并位于磁盘某处的页文件中的数据。在负载较重的系统中,每个进程所使用的虚拟字节总数将大大超过机器的实际内存。

所以关系是:

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

这里还有另一个问题;正如共享库可以在应用程序模块中分配内存,导致应用程序的私有字节中报告潜在的假阳性,你的应用程序也可能最终在共享模块中分配内存,导致错误的底片。这意味着您的应用程序实际上有可能存在内存泄漏,而这种泄漏根本不会在私有字节中表现出来。不太可能,但有可能。

私有字节是你的可执行文件所使用的内存量的一个合理的近似,可以用来帮助缩小列出潜在的内存泄漏的候选对象;如果您看到数字不断地、无休止地增长,您就会想要检查这个过程是否有泄漏。然而,这并不能说明证明是否存在泄漏。

在Windows中检测/纠正内存泄漏最有效的工具之一实际上是Visual Studio(链接指向使用VS处理内存泄漏的页面,而不是产品页面)。Rational Purify是另一种可能。微软在这个问题上也有一个更普遍的最佳实践文档。在前一个问题中列出了更多的工具。

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

您不应该尝试使用perfmon、任务管理器或任何类似的工具来确定内存泄漏。它们有助于识别趋势,但仅此而已。他们报告的绝对数字太模糊,而且是聚合的,对特定任务(如内存泄漏检测)没有用处。

之前对这个问题的回答已经很好地解释了各种类型是什么。

你询问工具推荐: 我推荐内存验证器。能够监视执行数十亿内存分配的应用程序

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

免责声明:我设计了内存验证器。

这里有一个有趣的讨论: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);

然后私有字节正确地反映分配和释放。

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

关于Windows内存管理的一个很好的概述可以在视频"内存管理的奥秘被揭示"在MSDN上:它涵盖了比跟踪内存泄漏所需的更多主题(例如工作集管理),但在相关主题中提供了足够的细节。


为了让您对perfmon计数器描述的问题有一个提示,下面是关于来自"私有字节性能计数器-小心!< / em >"在MSDN上:

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

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

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


从“# EYZ0"在MSDN上:

3.3私有字节

3.3.1描述

私有内存,定义为分配给某个进程的内存,该内存不能被其他进程共享。当在一台机器上执行多个这样的进程时,这种内存比共享内存更昂贵。(传统的)非托管dll中的私有内存通常由c++静态组成,占dll总工作集的5%。