虚拟地址空间碎片

时间:2012-05-04 20:58:26

标签: memory windbg virtual-memory

我正在调查虚拟地址空间碎片。我遇到的问题是对VirtualAlloc的调用可能有很多来源(LOH,内存映射,......)

我可以从转储文件中识别该函数的调用者吗?弄清楚我的问题的来源?

2 个答案:

答案 0 :(得分:1)

您必须为您的app启用gflags用户堆栈跟踪,您可以从命令行或WinDbg中执行此操作,如果来自WinDbg:

!gflag +ust

然后你需要为给定的堆积做!heap -s!heap -stat -h XX将转储更具体的统计数据,我建议在这里执行内存转储.dump /ma c:\first.dmp然后执行导致碎片,按ctrl+break并再次输入!heap -s并再次进入内存转储.dump /ma c:\second.dmp,重新进入WinDbg。

内存转储和堆摘要的原因是您可以分析哪些堆正在增加或返回,打开转储并对这些快照执行分析,将结果转储到文本文件中并对结果执行差异。

因此,如果您确定了一个正在增加的特定堆块,那么您可以转储该块!heap -p -a xxxx的每个分配,其中xxxx是您的堆块,我建议您设置WinDbg将输出写入文件,因为这将在第二个内存转储上重复.logfile c:\first.txt重复并执行差异以查看正在发生的其他分配。

此外,您可以转储堆的统计信息,这将为您提供分配大小的细分,这也可能为您提供线索。无论如何,只要你有带有私有符号的pdbs,那么你就可以识别谁使用完整的调用栈进行分配。

修改

有一篇文章可以帮助您:http://bugslasher.net/2011/01/15/memory-exhaustion-even-if-a-large-enough-free-memory-segment-is-available/

如果您可以获取虚拟地址,那么您可以使用!pte addresspfn frameNum转储其他信息,您可以从{{1}的结果中获取虚拟地址的页面帧编号}。

!pte将显示有关虚拟内存使用情况的一些统计信息,但不会更多,另一个是您可以在调用!vm 1时设置断点并转储调用堆栈和本地变量(如果使用) virtualAlloc然后这将显示堆栈帧之间的字节距离,这可能表示大量分配,我会将此信息写入日志文件并稍后在2个转储之间进行比较。

答案 1 :(得分:0)

首先,您必须为OS组件和您的程序设置pdb符号:在符号路径窗口中设置字符串,如下所示

SRV * F:\符号\ websymbols * HTTP://msdl.microsoft.com/download/symbols

并添加程序私有符号的路径。 执行此操作后,您可以在命令kb上看到prety堆栈跟踪。堆栈中首次出现的程序是调用函数。