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

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

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

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

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

以下是我的问题:

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

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

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

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


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

Private Bytes refer to the amount of memory that the process executable has asked for - not necessarily the amount it is actually using. They are "private" because they (usually) exclude memory-mapped files (i.e. shared DLLs). But - here's the catch - they don't necessarily exclude memory allocated by those files. There is no way to tell whether a change in private bytes was due to the executable itself, or due to a linked library. Private bytes are also not exclusively physical memory; they can be paged to disk or in the standby page list (i.e. no longer in use, but not paged yet either).

Working Set refers to the total physical memory (RAM) used by the process. However, unlike private bytes, this also includes memory-mapped files and various other resources, so it's an even less accurate measurement than the private bytes. This is the same value that gets reported in Task Manager's "Mem Usage" and has been the source of endless amounts of confusion in recent years. Memory in the Working Set is "physical" in the sense that it can be addressed without a page fault; however, the standby page list is also still physically in memory but not reported in the Working Set, and this is why you might see the "Mem Usage" suddenly drop when you minimize an application.

虚拟字节是整个进程占用的虚拟地址空间的总和。这类似于工作集,因为它包括内存映射文件(共享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计数器描述问题的提示,下面是来自MSDN上“private bytes Performance counter—Beware!”的关于私有字节的内部故事:

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


摘自MSDN上的“绩效规划”:

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