我正在使用的应用程序表现出以下行为:
在特定的高内存操作期间,任务管理器(内存使用情况统计信息)下的进程内存使用量达到大约2.5GB的峰值(注意:注册表项已经过设置允许这样,因为32位Windows下的进程通常最多有2GB)
操作完成后,流程大小缓慢开始以每秒1MB的速度递减。
我正在试图找出最简单的方法来快速确定谁释放了这个记忆,以及它在哪里被释放。
我在将内存探查器附加到我的代码时遇到问题,我并不特别想覆盖new
/ delete
运算符来跟踪分配/解除分配(IOW,我想做这没有重新编译我的代码。)
有人可以通过Visual Studio调试器提供有关如何执行此操作的任何有用建议吗?
更新
我还应该提到它是一个多线程应用程序,因此暂停应用程序并通过调试器分析调用堆栈并不是最理想的选择。我考虑一次冻结一个不同的线程,看看内存是否停止减少,但我相当肯定这会导致应用程序崩溃。
答案 0 :(得分:2)
啊!你正在看错了柜台!
Mem Usage
没有告诉你内存被释放。只有工作装置被清除!这可能意味着某些其他应用程序需要内存,或者VMM决定将某些进程的页面标记为待机状态,以便快速使用其他某些进程。这并不意味着正在调用VirtualFree
,HeapFree
或任何其他自由函数。
查看提交大小(VM大小,私有字节等)。
但是如果您仍然想知道何时释放或释放内存或者有什么内容,那么请打破一些免费通话。例如。 (对于Visual C ++)
{,,kernel32.dll}HeapFree
或
{,,msvcr80.dll}free
等
或者只是上面的常规函数断点。只要确保它解析了地址。
cdb / WinDbg让你通过
来做bp kernel32!HeapFree
bp msvcrt!free
等
名称可能会有所不同,具体取决于您使用的CRT版本以及链接方式(通过/MT
或/MD
及其变体)
答案 1 :(得分:0)
您可能会发现本文很有用: http://www.gamasutra.com/view/feature/1430/monitoring_your_pcs_memory_usage_.php?print=1
基本上我的想法是挂钩低级别的分配功能。
答案 2 :(得分:0)
有几个不同的想法:
C运行时具有一组内存调试功能;你需要重新编译。您可以在计算完成时获得快照,然后使用_CrtMemDifference查看更改的内容。
或者,您可以在调试器中附加到进程,并使其在释放内存之前和之后转储核心。使用NTSD,你可以看到堆周围的东西,以及东西的大小。 (你需要大量的磁盘空间,并且需要相当多的耐心。)有一个设置(我认为你通过gflags,但我不记得了)导致它将一块调用堆栈保存为转储的一部分;使用它你可以弄清楚什么样的对象被释放。不幸的是,它只存储4或5个堆栈帧,所以你可能需要做一些更聪明的事情,作为下一步找出它被释放的位置。要么查看代码(“是的,只有一个地方可以发生这种情况”)或在这些析构函数中加入断点,或者在分配和解除分配中添加跟踪。
答案 3 :(得分:0)
如果您的内存管理器将自由数据擦除到已知值(通常类似于0xfeeefeee),您可以在您感兴趣的某个特定实例上设置数据断点。当它被释放时,断点当内存被擦除时会触发。
答案 4 :(得分:0)
我建议您查看Windows调试工具附带的UMDH工具(您可以在调试工具帮助中找到用法和示例)。您可以使用堆栈跟踪快照运行进程的堆分配并比较它们。
答案 5 :(得分:0)
您可以尝试Memory Validator来监控分配和解除分配。 Memory Validator有一些功能可以帮助您确定数据被解除分配的位置:
热点视图。这可以显示所有分配和解除分配的树,或仅显示所有分配或仅显示所有解除分配。它将数据显示为内存活动的百分比(基于在给定位置分配的内存量(de))。
分析视图。您可以执行查询,询问给定地址范围内的数据。您可以将这些查询限制为alloc,realloc和dealloc行为中的任何一个。
对象视图。您可以按类型查看分配,并查看每种类型的最大对象数(以及许多其他统计数据)。右键单击类型以获取上下文菜单,选择show all deallocations - 将在Analysis选项卡上显示该类型的释放位置。
我认为热点视图可能会为您提供所需的洞察力。