Mar*_* Ba 21 c++ debugging heap windbg crash-dumps
我们收到了客户的本机(完整)故障转储文件.在Visual Studio(2005)调试器中打开它表明我们遇到了由试图分配~10MB块的realloc调用引起的崩溃.转储文件非常大(1.5 GB - 通常它们更像500 MB).
因此,我们得出结论,我们有一个内存"泄漏"或失控的分配,要么完全耗尽进程的内存,要么至少将其分散到足以使realloc失败.(请注意,这个realloc用于分配日志记录缓冲区的操作,我们并不感到惊讶它在这里失败,因为一次性使用10MB将是我们除了一些非常大的非常不可更改的缓冲区之外的更大分配之一 - 问题本身可能与此特定分配无关.)
编辑:在下面的Lex Li评论交换之后,我应该补充:这对我们来说是不可再现的(此刻).这只是一个客户转储显然显示失控的内存消耗.
现在我们有一个转储文件,但是我们如何找到导致内存使用过多的原因?
我们使用DebugDiag工具来分析转储文件(所谓的内存压力分析器),这是我们得到的:
Report for DumpFM...dmp
Virtual Memory Summary
----------------------
Size of largest free VM block 62,23 MBytes
Free memory fragmentation 81,30%
Free Memory 332,87 MBytes (16,25% of Total Memory)
Reserved Memory 0 Bytes (0,00% of Total Memory)
Committed Memory 1,67 GBytes (83,75% of Total Memory)
Total Memory 2,00 GBytes
Largest free block at 0x00000000`04bc4000
Loaded Module Summary
---------------------
Number of Modules 114 Modules
Total reserved memory 0 Bytes
Total committed memory 3,33 MBytes
Thread Summary
--------------
Number of Threads 56 Thread(s)
Total reserved memory 0 Bytes
Total committed memory 652,00 KBytes
Run Code Online (Sandbox Code Playgroud)
这只是为了得到一点背景.我相信更有趣的是:
Heap Summary
------------
Number of heaps 26 Heaps
Total reserved memory 1,64 GBytes
Total committed memory 1,61 GBytes
Top 10 heaps by reserved memory
-------------------------------
0x01040000 1,55 GBytes
0x00150000 64,06 MBytes
0x010d0000 15,31 MBytes
...
Top 10 heaps by committed memory
--------------------------------
0x01040000 1,54 GBytes
0x00150000 55,17 MBytes
0x010d0000 6,25 MBytes
...
Run Code Online (Sandbox Code Playgroud)
现在,看一下堆0x01040000(1.5 GB),我们看到:
Heap 5 - 0x01040000
-------------------
Heap Name msvcr80!_crtheap
Heap Description This heap is used by msvcr80
Reserved memory 1,55 GBytes
Committed memory 1,54 GBytes (99,46% of reserved)
Uncommitted memory 8,61 MBytes (0,54% of reserved)
Number of heap segments 39 segments
Number of uncommitted ranges 41 range(s)
Size of largest uncommitted range 8,33 MBytes
Calculated heap fragmentation 3,27%
Segment Information
-------------------
Base Address | Reserved Size | Committed Size | Uncommitted Size | Number of uncommitted ranges | Largest uncommitted block | Calculated heap fragmentation
0x01040640 64,00 KBytes 64,00 KBytes 0 Bytes 0 0 Bytes 0,00%
0x01350000 1.024,00 KBytes 1.024,00 KBytes 0 Bytes 0 0 Bytes 0,00%
0x02850000 2,00 MBytes 2,00 MBytes 0 Bytes 0 0 Bytes 0,00%
...
Run Code Online (Sandbox Code Playgroud)
无论如何,这段信息是什么?
查看列出的分配:
Top 5 allocations by size
-------------------------
Allocation Size - 336 1,18 GBytes
Allocation Size - 1120004 121,77 MBytes
...
Top 5 allocations by count
--------------------------
Allocation Size - 336 3760923 allocation(s)
Allocation Size - 32 1223794 allocation(s)
...
Run Code Online (Sandbox Code Playgroud)
我们可以看到,显然MSVCR80堆在336字节处保存3.760.923个分配.这很明显我们用大量的小分配来清理我们的内存,但是我们怎么能得到更多关于这些分配来自哪里的信息呢?
如果我们以某种方式可以对这些分配地址中的一些进行采样,然后检查过程映像中这些地址的使用位置,那么 - 假设这些分配的很大一部分是我们"泄漏"的原因 - 我们可能会找到这些失控的分配来自.
不幸的是,我真的不知道如何从转储中获取更多信息.
我如何检查这个堆以查看一些"336"分配地址?
如何在转储中搜索这些地址,然后如何找到转储中哪个指针变量(如果有)保留在这些地址上?
有关使用DebugDiag,WinDbg或任何其他工具的任何提示都可以提供帮助!另外,如果您不同意我上面的任何分析,请告诉我们!谢谢!
小智 10
你可以:
!heap -stat -h 0x01040000,这将使你的块的大小,那么这个传递的大小,以!heap -flt s 大小,将列出该尺寸的所有块.然后,您可以使用任何显示内存的命令(如dc)查看该块.gflags.exe实用程序(gflags -i your.exe +ust)激活堆栈回溯功能.然后运行您的应用程序,获取转储,并使用!heap -flt s列出块.然后命令!heap -p -a blockaddress 将转储分配块的函数堆栈.