一般我用两种方法:
1. 用Debug Diagnostic Tool的Leak监测分析功能,注意配置好PDB文件。
DebugDiag 会生成完整的Leak Report。看看帮助很方便。
2. 用WinDBG的!heap扩展命令。注意要为你的程序打开Normal PageHeap。
然后当内存出现明显泄漏时用 !heap -l 命令分析内存。-l 参数使用类似Java/C#的Garbage Collection算法,这样能找到大部分在程序中没有被引用的HeapBlock。
这是一个示例输出:
0:011> !heap -lSearching the memory for potential unreachable busy blocks.......Heap 017a0000Scanning VM ...Scanning references from 3586 busy blocks (0 MBytes) ...Entry User Heap Segment Size PrevSize Unused Flags-----------------------------------------------------------------------------00253198 002531a0 00250000 00250000 b8 78 14 busy extra 00253250 00253258 00250000 00250000 78 b8 13 busy extra 00286a38 00286a40 00250000 00250000 b8 b8 15 busy extra 00286af0 00286af8 00250000 00250000 b8 b8 15 busy extra 00286ba8 00286bb0 00250000 00250000 b8 b8 15 busy extra 00286c60 00286c68 00250000 00250000 b8 b8 15 busy extra 00286d18 00286d20 00250000 00250000 b8 b8 15 busy extra 00286dd0 00286dd8 00250000 00250000 b8 b8 15 busy extra
找到最常出现的Size值(这里是b8),一般就是持续泄漏的内存块大小。随便选一行,记下Entry地址(比如00286a3)。
dt _DPH_BLOCK_INFORMATION 00286a3 + 8 //8 是HeapEntry结构的大小,跟在其后的就是PageHeap meta data,结构名是_DPH_BLOCK_INFORMATION.
0:011> dt _DPH_BLOCK_INFORMATION 00286a3 + 8ntdll!_DPH_BLOCK_INFORMATION +0x000 StartStamp : 0xabcdaaaa +0x004 Heap : 0x80151000 +0x008 RequestedSize : 0x7b +0x00c ActualSize : 0xa3 +0x010 FreeQueue : _LIST_ENTRY [ 0x2e - 0x0 ] +0x010 TraceIndex : 0x2e +0x018 StackTrace : 0x00357140 +0x01c EndStamp : 0xdcbaaaaa
看到StackTrace那行,这是相应的user mode stack trace database的地址。
0:011> dds 0x0035714000357140 abcdaaaa......00357160 7c949d18 ntdll!RtlAllocateHeapSlowly+0x4400357164 7c91b298 ntdll!RtlAllocateHeap+0xe6400357168 004017fe 06_DebugDiag_MemoryLeak!MyHeapAlloc+0x1e [g:\debugging101\projects\06_debugdiag_memoryleak\06_debugdiag_memoryleak\06_debugdiag_memoryleak.cpp @ 11]0035716c 0040182b 06_DebugDiag_MemoryLeak!WorkerThread+0x1b [g:\debugging101\projects\06_debugdiag_memoryleak\06_debugdiag_memoryleak\06_debugdiag_memoryleak.cpp @ 27]00357170 7c80b683 kernel32!BaseThreadStart+0x37
这就是上次通过Heap Manager函数操作这个HeapBlock的StackTrace,一般也就是分配这个Block的地方。
希望可以帮到你。