我正在尝试使用 perfmon windows 实用程序来调试进程中的内存泄漏。
perfmon 是这样解释这些术语的:
工作集是此进程的工作集的当前大小(以字节为单位)。工作集是进程中的线程最近接触的内存页集。如果计算机中的可用内存高于阈值,则页面将留在进程的工作集中,即使它们没有被使用。当可用内存低于阈值时,将从工作集中修剪页面。如果需要它们,它们将在离开主存储器之前被软故障返回到工作集中。
Virtual Bytes 是进程正在使用的虚拟地址空间的当前大小(以字节为单位)。使用虚拟地址空间并不一定意味着相应使用磁盘或主内存页面。虚拟空间是有限的,进程可能会限制其加载库的能力。
Private Bytes 是当前进程分配的不能与其他进程共享的内存大小(以字节为单位)。
这些是我的问题:
是我应该测量的私有字节,以确保进程是否有任何泄漏,因为它不涉及任何共享库,并且任何泄漏(如果发生)将来自进程本身?
进程消耗的总内存是多少?是虚拟字节还是虚拟字节和工作集的总和?
Private Bytes、Working Set 和 Virtual Bytes 之间有什么关系吗?
是否有任何其他工具可以更好地了解内存使用情况?
对这个问题的简短回答是,这些值都不是可执行文件实际使用多少内存的可靠指标,而且它们都不适合调试内存泄漏。
私有字节是指进程可执行文件要求的内存量 - 不一定是它实际使用的内存量。它们是“私有的”,因为它们(通常)不包括内存映射文件(即共享 DLL)。但是 - 这里有一个问题 - 它们不一定排除这些文件分配的内存。无法判断私有字节的变化是由于可执行文件本身还是由于链接库。私有字节也不仅仅是物理内存;它们可以被分页到磁盘或备用页面列表中(即不再使用,但也没有分页)。
工作集是指进程使用的总物理内存(RAM)。但是,与私有字节不同,这还包括内存映射文件和各种其他资源,因此它的测量精度甚至不如私有字节。这与任务管理器的“内存使用情况”中报告的值相同,并且近年来一直是无数混乱的根源。工作集中的内存是“物理的”,因为它可以在没有页面错误的情况下被寻址;但是,备用页面列表仍然物理上位于内存中,但未在工作集中报告,这就是为什么您在最小化应用程序时可能会看到“Mem Usage”突然下降的原因。
Virtual Bytes 是整个进程占用的总虚拟地址空间。这就像工作集,从某种意义上说,它包括内存映射文件(共享 DLL),但它还包括备用列表中的数据和已经被分页并位于磁盘某处的页面文件中的数据。在重负载下,系统上每个进程使用的总虚拟字节数加起来会比机器实际拥有的内存多得多。
所以关系是:
Private Bytes 是您的应用实际分配的,但包括页面文件的使用;
工作集是非分页私有字节加上内存映射文件;
虚拟字节是工作集加上分页的私有字节和备用列表。
这里还有另一个问题;正如共享库可以在您的应用程序模块内分配内存,从而导致在您的应用程序的私有字节中报告潜在的误报,您的应用程序也可能最终在共享模块内分配内存,从而导致误报。这意味着您的应用程序实际上可能存在根本不会在私有字节中表现出来的内存泄漏。不太可能,但可能。
Private Bytes 是可执行文件正在使用的内存量的合理近似值,可用于帮助缩小内存泄漏的潜在候选者列表;如果您看到这个数字不断增长且无休止地增长,您会想要检查该过程是否存在泄漏。但是,这不能证明存在或不存在泄漏。
在 Windows 中检测/纠正内存泄漏的最有效工具之一实际上是 Visual Studio(链接转到使用 VS 处理内存泄漏的页面,而不是产品页面)。 Rational Purify 是另一种可能性。 Microsoft 在此主题上也有一个更通用的 best practices document。此previous question中列出了更多工具。
我希望这能解决一些问题!跟踪内存泄漏是调试中最困难的事情之一。祝你好运。
perfmon 计数器的定义从一开始就被打破,并且由于某种原因似乎很难纠正。
MSDN 上的视频“Mysteries of Memory Management Revealed”中提供了对 Windows 内存管理的一个很好的概述:它涵盖了比跟踪内存泄漏所需的更多主题(例如工作集管理),但在相关主题中提供了足够的详细信息。
为了让您了解 perfmon 计数器描述的问题,这里是关于 MSDN 上“Private Bytes Performance Counter -- Beware!”的私有字节的内幕:
问:什么时候私有字节不是私有字节? A:当它不是居民时。 Private Bytes 计数器报告进程的提交费用。也就是说,在交换文件中已分配的空间量,用于在私有内存被换出时保存私有内存的内容。注意:我避免使用“保留”一词,因为可能与未提交的保留状态下的虚拟内存混淆。
来自 MSDN 上的“Performance Planning”:
3.3 私有字节 3.3.1 描述 私有内存,被定义为分配给一个进程的内存,不能被其他进程共享。当在一台机器上执行多个此类进程时,此内存比共享内存更昂贵。 (传统的)非托管 dll 中的私有内存通常由 C++ 静态构成,并且大约占 dll 总工作集的 5%。
您不应该尝试使用 perfmon、任务管理器或任何类似的工具来确定内存泄漏。它们有助于识别趋势,但仅此而已。他们以绝对值报告的数字过于模糊和汇总,无法用于特定任务,例如内存泄漏检测。
之前对这个问题的回答已经很好地解释了各种类型是什么。
你问一个工具推荐:我推荐 Memory Validator。能够监控进行数十亿内存分配的应用程序。
http://www.softwareverify.com/cpp/memory/index.html
免责声明:我设计了内存验证器。
这里有一个有趣的讨论:http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/307d658a-f677-40f2-bdef-e6352b0bfe9e/ 我对这个线程的理解是,释放小分配不会反映在 Private Bytes 或 Working Set 中。
长话短说:
如果我打电话
p=malloc(1000);
free(p);
那么 Private Bytes 只反映分配,而不是释放。
如果我打电话
p=malloc(>512k);
free(p);
那么私有字节正确地反映了分配和释放。
不定期副业成功案例分享