我正在尝试使用perfmon Windows实用程序来调试进程中的内存泄漏。
这就是perfmon解释这些术语的方式:
工作集是此进程的工作集的当前大小(以字节为单位)。工作集是过程中线程最近触及的一组内存页面。如果计算机中的可用内存超过阈值,则即使不使用页面,页面也会保留在进程的工作集中。当可用内存低于阈值时,将从工作集中剪裁页面。如果需要它们,则在离开主存储器之前,它们将被软故障返回到工作集中。
虚拟字节是进程正在使用的虚拟地址空间的当前大小(以字节为单位)。使用虚拟地址空间不一定意味着相应地使用磁盘或主存储器页面。虚拟空间是有限的,并且该过程可以限制其加载库的能力。
专用字节数是此进程分配的内存的当前大小(以字节为单位),无法与其他进程共享。
这些是我的问题:
是否应该测量私有字节,以确定进程是否有任何泄漏,因为它不涉及任何共享库,如果发生任何泄漏,将来自进程本身?
该进程消耗的总内存是多少?它是虚拟字节还是虚拟字节和工作集的总和?
私有字节,工作集和虚拟字节之间是否有任何关系?
还有其他工具可以更好地了解内存使用情况吗?
答案 0 :(得分:463)
这个问题的简短回答是这些值都不是可执行文件实际使用的内存量的可靠指标,并且它们都不适合调试内存泄漏。 < / p>
私有字节是指进程可执行文件要求的内存量 - 不一定是实际使用的数量。它们是“私有的”,因为它们(通常)排除了内存映射文件(即共享DLL)。但是 - 这是捕获 - 它们不一定排除那些文件分配的内存 。没有办法判断私有字节的更改是由于可执行文件本身还是由于链接库。专用字节也不专门的物理内存;它们可以被分页到磁盘或备用页面列表(即不再使用,但也没有被分页)。
工作集是指进程使用的总物理内存(RAM)。但是,与专用字节不同,这还包括内存映射文件和各种其他资源,因此它比专用字节的测量精度更低。这与在任务管理器的“内存使用”中报告的值相同,并且近年来一直是无穷无尽的混淆源。工作集中的内存是“物理的”,因为它可以在没有页面错误的情况下进行处理;但是,备用页面列表也仍然在物理上在内存中但未在工作集中报告,这就是为什么在最小化应用程序时可能会看到“内存使用”突然丢失的原因。
虚拟字节是整个过程占用的总虚拟地址空间。这就像工作集一样,它包含内存映射文件(共享DLL),但它还包括备用列表中的数据和已经被分页的数据,并且位于磁盘上的页面文件中。重负载下系统上每个进程使用的总虚拟字节数将比机器实际拥有的内存大得多。
所以关系是:
这里还有另一个问题;正如共享库可以在应用程序模块中分配内存,导致应用程序的私有字节中报告的潜在误报,您的应用程序也可能最终在共享模块内分配内存,导致错误的否定。这意味着您的应用程序实际上可能存在内存泄漏,而这种内存泄漏根本不会出现在Private Bytes中。不太可能,但可能。
私有字节是您的可执行文件使用的内存量的合理近似,可用于帮助缩小潜在候选列表以进行内存泄漏;如果你看到这个数字不断增长并且不断增长,你会想要检查这个过程是否有泄漏。但是,这不能证明存在或不存在泄漏。
在Windows中检测/纠正内存泄漏的最有效工具之一实际上是Visual Studio(链接转到使用VS进行内存泄漏的页面,而不是产品页面)。 Rational Purify是另一种可能性。微软在这个问题上也有一个更普遍的best practices document。此previous question中列出了更多工具。
我希望这能清除一些事情!追踪内存泄漏是调试中最困难的事情之一。祝你好运。
答案 1 :(得分:9)
您不应该尝试使用perfmon,任务管理器或任何类似的工具来确定内存泄漏。它们有助于识别趋势,但不是很多。他们以绝对术语报告的数字过于模糊和汇总,无法用于特定任务,如内存泄漏检测。
之前对这个问题的回复很好地解释了各种类型的内容。
您询问工具建议: 我推荐Memory Validator。能够监控产生数十亿内存分配的应用程序。
http://www.softwareverify.com/cpp/memory/index.html
免责声明:我设计了Memory Validator。
答案 2 :(得分:8)
perfmon计数器的定义从一开始就被打破了,由于某些原因似乎太难以纠正。
视频&#34; Mysteries of Memory Management Revealed&#34;中提供了有关Windows内存管理的概述。在MSDN上:它涵盖了跟踪内存泄漏所需的更多主题(例如工作集管理),但在相关主题中提供了足够的细节。
为了向您提供有关perfmon计数器描述的问题的提示,这里是关于来自&#34; Private Bytes Performance Counter -- Beware!&#34;的私有字节的内幕故事。在MSDN上:
问:私有字节何时不是私有字节?
答:当它不驻留时。
Private Bytes计数器报告进程的提交费用。也就是说,交换文件中分配的空间量,用于在交换出来时保存私有内存的内容。注意:我避免使用&#34;保留&#34;因为可能与未提交的保留状态中的虚拟内存混淆。
来自&#34; Performance Planning&#34;在MSDN上:
3.3私人字节
3.3.1说明
专用内存,定义为为进程分配的内存,无法由其他进程共享。当多台此类进程在计算机上执行时,此内存比共享内存更昂贵。 (传统)非托管dll中的私有内存通常由C ++静态构成,并且大约是dll总工作集的5%。
答案 3 :(得分:5)
这里有一个有趣的讨论: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);
然后私有字节正确反映分配和释放。