C++ 有没有办法为所有堆userptr获取userstack
我正在通读这篇文章。我试图找到一种方法来打印所有userptr的userstack,这些userptr在针对特定大小的内存块筛选heap时出现。这可能吗? 我希望实现以下目标:C++ 有没有办法为所有堆userptr获取userstack,c++,memory-leaks,windbg,C++,Memory Leaks,Windbg,我正在通读这篇文章。我试图找到一种方法来打印所有userptr的userstack,这些userptr在针对特定大小的内存块筛选heap时出现。这可能吗? 我希望实现以下目标: foreach(userPtr) dump_to_a_file !heap -p -a userPtr 其中userPtr为:userPtr如下 HEAP_ENTRY Size Prev Flags UserPtr UserSize - state 003360e0 03f0 000
foreach(userPtr)
dump_to_a_file !heap -p -a userPtr
其中userPtr为:userPtr如下
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
003360e0 03f0 0000 [07] 003360e8 01f64 - (busy)
00338060 03f0 03f0 [07] 00338068 01f64 - (busy)
00339fe0 03f0 03f0 [07] 00339fe8 01f64 - (busy)
我尝试这样做是为了避免手动检查数千个这样的UserPtr。谢谢你能给我的帮助 这是
的输出!heap-flt s xxx
命令,该命令包含堆条目表前后的大量文本。让我们通过做hack来去掉那些额外的文本
.shell -ci "!heap -flt s xxx" find "["
现在,它的输出非常稳定,可用于foreach循环:
.foreach (userptr {.shell -ci "!heap -flt s xxx" find "["}) { .echo ${userptr}}
看看它是如何分割每条线的。让我们使用/ps4/ps7
去掉前4个令牌(entry、size、prev、flags)和后3个令牌(usersize、、state)
.foreach /pS 4 /ps 7 (userptr {.shell -ci "!heap -flt s xxx" find "["}) { .echo ${userptr}}
现在您已经有了纯地址,请使用它做一些有用的事情,即!堆-p-a
.foreach /pS 4 /ps 7 (userptr {.shell -ci "!heap -flt s xxx" find "["}) { !heap -p -a ${userptr}}
要将其转储到文件中,请用日志(.logopen
和.logclose
)将其包围:
好了。您可以使用
umdh.exe
进行此操作。Umdh可以转储所有分配,或者转储同一进程的两个快照之间的增量,这是查找内存泄漏最方便的方法。您可以在安装Windows调试器工具的位置找到该工具
使用umdh.exe时需要知道的一个问题是,在执行增量操作(即比较进程的两个快照)时,它只解析符号。如果您真的需要每一个调用堆栈,只需在流程执行的最开始创建第一个快照
Umdh.exe还将具有相同调用堆栈的分配聚合到bucket中,因此在diff输出中,您将看到如下内容:
+ 18f0 ( 2354 - a64) 11 allocs BackTrace113457DC
+ c ( 11 - 5) BackTrace113457DC allocations
ntdll!RtlAllocateHeap+38CB9
msvcrt!_calloc_impl+134
msvcrt!_calloc_crt+16
msvcrt!_CRTDLL_INIT+FC
ntdll!LdrxCallInitRoutine+16
ntdll!LdrpCallInitRoutine+43
ntdll!LdrpInitializeThread+106
ntdll!_LdrpInitialize+6A
ntdll!LdrInitializeThunk+10
这是11个分配的调用堆栈示例,快照之间此调用堆栈的分配数从5增加到11,这些分配占用的内存从0xa64增加到0x2354字节
演示如何使用umdh.exe的示例步骤:
- 设置umdh所需的\u NT\u SYMBOL\u PATH环境变量。假设您所在的目录中有您的专用符号(%CD%)
- 在调试器下启动进程,在断点或任何需要的地方停止进程
- 创建第一个快照:
- 继续执行流程,在需要的地方再次停止李>
- 创建第二个快照:
- 创建已解析符号的差异:
你知道在
的一些输出前面的星号是什么意思吗!heap-p-all
。它严重扰乱了我的.foreach
循环。我试图通过排除它来获得有用的结果,但这让我感到疑惑。使用您的示例,我得到了.foreach/ps4/ps3(userptr{.shell-ci”!heap-p-all“find”busy | find/V“*”}){!heap-p-a${userptr}代码>对于大转储,命令(!heap-flt s xxx)返回巨大的结果。我只想看到来自的前1000个结果的调用堆栈(!heap-p-a${userptr})!堆-flt s xxx。这可能吗?@VivekRaja:正如你从Lieven的评论中看到的,这个过程仍然脆弱。对于更高级的文本处理,我将尝试PyKd并编写Python脚本。@托马斯·韦勒:谢谢您提供有关PyKd的信息。这真的很有帮助。使用Python脚本,现在我能够过滤繁忙分配的前n个调用堆栈。
+ 18f0 ( 2354 - a64) 11 allocs BackTrace113457DC
+ c ( 11 - 5) BackTrace113457DC allocations
ntdll!RtlAllocateHeap+38CB9
msvcrt!_calloc_impl+134
msvcrt!_calloc_crt+16
msvcrt!_CRTDLL_INIT+FC
ntdll!LdrxCallInitRoutine+16
ntdll!LdrpCallInitRoutine+43
ntdll!LdrpInitializeThread+106
ntdll!_LdrpInitialize+6A
ntdll!LdrInitializeThunk+10
set _NT_SYMBOL_PATH=%CD%;srv*http://msdl.microsoft.com/download/symbols
umdh -p: -f:MyFirstSnapshot.txt
umdh -p: -f:MySecondSnapshot.txt
umdh MyFirstSnapshot.txt MySecondSnapshot.txt -f:MyDiff.txt