Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/127.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 有没有办法为所有堆userptr获取userstack_C++_Memory Leaks_Windbg - Fatal编程技术网

C++ 有没有办法为所有堆userptr获取userstack

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

我正在通读这篇文章。我试图找到一种方法来打印所有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 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%)
设置\u NT\u符号\u路径=%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
你知道在
的一些输出前面的星号是什么意思吗!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