有没有办法获得所有堆userptr的userstack

时间:2014-06-27 12:06:56

标签: c++ memory-leaks windbg

我正在阅读这篇文章detecting memory leak using windbg。我正在尝试找到一种方法来打印所有userptack的用户插件,这些用户在针对特定大小的内存块进行过滤时会出现。这可能吗 ? 我希望实现类似的目标:

  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。感谢您提供的任何帮助。

2 个答案:

答案 0 :(得分:4)

这是!heap -flt s xxx命令的输出,其中包含堆条目表之前和之后的大量文本。让我们通过做黑客

来摆脱那些额外的文本
.shell -ci "!heap -flt s xxx" find "["

现在它的输出非常稳定,可用于foreach循环:

.foreach (userptr {.shell -ci "!heap -flt s xxx" find "["}) { .echo ${userptr}}

了解它如何分割每一行。让我们使用/pS 4 /ps 7摆脱前4个令牌(条目,大小,上一个,标志)和最后三个令牌(用户名, - ,状态)。

.foreach /pS 4 /ps 7 (userptr {.shell -ci "!heap -flt s xxx" find "["}) { .echo ${userptr}}

现在您已拥有纯地址,请使用!heap -p -a

执行一些有用的操作
.foreach /pS 4 /ps 7 (userptr {.shell -ci "!heap -flt s xxx" find "["}) { !heap -p -a ${userptr}}

要将其转储到文件中,请用日志(.logopen.logclose)将其包围:

.logopen d:\debug\logs\heap.log; .foreach /pS 4 /ps 7 (userptr {.shell -ci "!heap -flt s xxx" find "["}) { !heap -p -a ${userptr}}; .logclose

你去。

答案 1 :(得分:1)

您可以使用umdh.exe。 Umdh可以转储所有分配,或者同一进程的两个快照之间的增量,这是查找内存泄漏的最方便的方法。您可以在安装Windows调试工具的位置找到该工具。

使用您需要知道的umdh.exe时的问题是,它仅在执行增量操作时解析符号,即比较进程的两个快照。如果你真的需要每个callstack,只需在流程执行的最初阶段制作一个快照。

Umdh.exe还将具有相同callstack的分配聚合到桶中,因此在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所需的_NT_SYMBOL_PATH环境变量。假设您所在的目录中有私人符号(%CD%)
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