如何使用windbg检测内存泄漏
1.设置符号路径
打开windbg,在菜单Symbol File PATH设置
"SRV*d:\symbols*http://msdl.microsoft.com/download/symbols"
d:\symbols是你本地磁盘的一个文件夹,用于下载微软的符号文件
另外,把调试的目标程序的PDB文件路径加到后面
例如:SRV*d:\symbols*http://msdl.microsoft.com/download/symbols;d:\Develop\projects\Service\bin\Release
2.启用跟踪用户模式下的栈信息
运行Gflags.exe /i xxx.exe +ust
xxx.exe是调试的目标程序名字
3.用windbg启动目标程序或附加到目标进程
4.查看堆栈信息
运行!heap -s
显示类似如下的结果
NtGlobalFlag enables following debugging aids for new heaps:
validate parameters
stack back traces
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
00150000 58000062 1024 12 12 1 1 1 0 0 L
00250000 58001062 64 24 24 15 1 1 0 0 L
00260000 58008060 64 12 12 10 1 1 0 0
00330000 58001062 261184 239484 239484 14 4 1 0 0
-----------------------------------------------------------------------------
从例子看到00330000的堆内存占用明显高
5.查看具体堆的统计信息
运行!heap -stat -h 00330000
显示这个堆的统计信息
显示类似如下结果
heap @ 00330000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
1f64 76c6 - e905f58 (99.99)
1800 1 - 1800 (0.00)
824 2 - 1048 (0.00)
238 2 - 470 (0.00)
244 1 - 244 (0.00)
4c 5 - 17c (0.00)
b0 2 - 160 (0.00)
86 2 - 10c (0.00)
50 3 - f0 (0.00)
74 2 - e8 (0.00)
38 4 - e0 (0.00)
48 3 - d8 (0.00)
c4 1 - c4 (0.00)
62 2 - c4 (0.00)
be 1 - be (0.00)
b8 1 - b8 (0.00)
ae 1 - ae (0.00)
ac 1 - ac (0.00)
55 2 - aa (0.00)
a4 1 - a4 (0.00)
可以看到有0x76c6个1f64字节的块被分配,占比为99.99%
6.显示块的内存地址
运行!heap -flt s 1f64
显示块大小为1f64的内存地址
_HEAP @ 150000
_HEAP @ 250000
_HEAP @ 260000
_HEAP @ 330000
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)
0033bf60 03f0 03f0 [07] 0033bf68 01f64 - (busy)
0033dee0 03f0 03f0 [07] 0033dee8 01f64 - (busy)
01420040 03f0 03f0 [07] 01420048 01f64 - (busy)
01421fc0 03f0 03f0 [07] 01421fc8 01f64 - (busy)
01423f40 03f0 03f0 [07] 01423f48 01f64 - (busy)
01425ec0 03f0 03f0 [07] 01425ec8 01f64 - (busy)
01427e40 03f0 03f0 [07] 01427e48 01f64 - (busy)
01429dc0 03f0 03f0 [07] 01429dc8 01f64 - (busy)
0142bd40 03f0 03f0 [07] 0142bd48 01f64 - (busy)
0142dcc0 03f0 03f0 [07] 0142dcc8 01f64 - (busy)
0142fc40 03f0 03f0 [07] 0142fc48 01f64 - (busy)
01431bc0 03f0 03f0 [07] 01431bc8 01f64 - (busy)
01433b40 03f0 03f0 [07] 01433b48 01f64 - (busy)
01435ac0 03f0 03f0 [07] 01435ac8 01f64 - (busy)
01437a40 03f0 03f0 [07] 01437a48 01f64 - (busy)
014399c0 03f0 03f0 [07] 014399c8 01f64 - (busy)
0143b940 03f0 03f0 [07] 0143b948 01f64 - (busy)
0143d8c0 03f0 03f0 [07] 0143d8c8 01f64 - (busy)
0143f840 03f0 03f0 [07] 0143f848 01f64 - (busy)
014417c0 03f0 03f0 [07] 014417c8 01f64 - (busy)
01443740 03f0 03f0 [07] 01443748 01f64 - (busy)
014456c0 03f0 03f0 [07] 014456c8 01f64 - (busy)
01447640 03f0 03f0 [07] 01447648 01f64 - (busy)
014495c0 03f0 03f0 [07] 014495c8 01f64 - (busy)
0144b540 03f0 03f0 [07] 0144b548 01f64 - (busy)
0144d4c0 03f0 03f0 [07] 0144d4c8 01f64 - (busy)
0144f440 03f0 03f0 [07] 0144f448 01f64 - (busy)
014513c0 03f0 03f0 [07] 014513c8 01f64 - (busy)
01453340 03f0 03f0 [07] 01453348 01f64 - (busy)
014552c0 03f0 03f0 [07] 014552c8 01f64 - (busy)
01457240 03f0 03f0 [07] 01457248 01f64 - (busy)
014591c0 03f0 03f0 [07] 014591c8 01f64 - (busy)
0145b140 03f0 03f0 [07] 0145b148 01f64 - (busy)
0145d0c0 03f0 03f0 [07] 0145d0c8 01f64 - (busy)
0145f040 03f0 03f0 [07] 0145f048 01f64 - (busy)
01460fc0 03f0 03f0 [07] 01460fc8 01f64 - (busy)
01462f40 03f0 03f0 [07] 01462f48 01f64 - (busy)
01464ec0 03f0 03f0 [07] 01464ec8 01f64 - (busy)
01466e40 03f0 03f0 [07] 01466e48 01f64 - (busy)
01468dc0 03f0 03f0 [07] 01468dc8 01f64 - (busy)
7.查看调用栈信息
可使用任一个UsrPtr的值来查询
!heap -p -a 0143d8c8
address 0143d8c8 found in
_HEAP @ 330000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0143d8c0 03f0 0000 [07] 0143d8c8 01f64 - (busy)
Trace: 0025
7c96d6dc ntdll!RtlDebugAllocateHeap+0x000000e1
7c949d18 ntdll!RtlAllocateHeapSlowly+0x00000044
7c91b298 ntdll!RtlAllocateHeap+0x00000e64
102c103e MSVCR90D!_heap_alloc_base+0x0000005e
102cfd76 MSVCR90D!_heap_alloc_dbg_impl+0x000001f6
102cfb2f MSVCR90D!_nh_malloc_dbg_impl+0x0000001f
102cfadc MSVCR90D!_nh_malloc_dbg+0x0000002c
102db25b MSVCR90D!malloc+0x0000001b
102bd691 MSVCR90D!operator new+0x00000011
102bd71f MSVCR90D!operator new[]+0x0000000f
4113d8 Test2!AllocateMemory+0x00000028
41145c Test2!wmain+0x0000002c
411a08 Test2!__tmainCRTStartup+0x000001a8
41184f Test2!wmainCRTStartup+0x0000000f
打开windbg,在菜单Symbol File PATH设置
"SRV*d:\symbols*http://msdl.microsoft.com/download/symbols"
d:\symbols是你本地磁盘的一个文件夹,用于下载微软的符号文件
另外,把调试的目标程序的PDB文件路径加到后面
例如:SRV*d:\symbols*http://msdl.microsoft.com/download/symbols;d:\Develop\projects\Service\bin\Release
2.启用跟踪用户模式下的栈信息
运行Gflags.exe /i xxx.exe +ust
xxx.exe是调试的目标程序名字
3.用windbg启动目标程序或附加到目标进程
4.查看堆栈信息
运行!heap -s
显示类似如下的结果
NtGlobalFlag enables following debugging aids for new heaps:
validate parameters
stack back traces
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
00150000 58000062 1024 12 12 1 1 1 0 0 L
00250000 58001062 64 24 24 15 1 1 0 0 L
00260000 58008060 64 12 12 10 1 1 0 0
00330000 58001062 261184 239484 239484 14 4 1 0 0
-----------------------------------------------------------------------------
从例子看到00330000的堆内存占用明显高
5.查看具体堆的统计信息
运行!heap -stat -h 00330000
显示这个堆的统计信息
显示类似如下结果
heap @ 00330000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
1f64 76c6 - e905f58 (99.99)
1800 1 - 1800 (0.00)
824 2 - 1048 (0.00)
238 2 - 470 (0.00)
244 1 - 244 (0.00)
4c 5 - 17c (0.00)
b0 2 - 160 (0.00)
86 2 - 10c (0.00)
50 3 - f0 (0.00)
74 2 - e8 (0.00)
38 4 - e0 (0.00)
48 3 - d8 (0.00)
c4 1 - c4 (0.00)
62 2 - c4 (0.00)
be 1 - be (0.00)
b8 1 - b8 (0.00)
ae 1 - ae (0.00)
ac 1 - ac (0.00)
55 2 - aa (0.00)
a4 1 - a4 (0.00)
可以看到有0x76c6个1f64字节的块被分配,占比为99.99%
6.显示块的内存地址
运行!heap -flt s 1f64
显示块大小为1f64的内存地址
_HEAP @ 150000
_HEAP @ 250000
_HEAP @ 260000
_HEAP @ 330000
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)
0033bf60 03f0 03f0 [07] 0033bf68 01f64 - (busy)
0033dee0 03f0 03f0 [07] 0033dee8 01f64 - (busy)
01420040 03f0 03f0 [07] 01420048 01f64 - (busy)
01421fc0 03f0 03f0 [07] 01421fc8 01f64 - (busy)
01423f40 03f0 03f0 [07] 01423f48 01f64 - (busy)
01425ec0 03f0 03f0 [07] 01425ec8 01f64 - (busy)
01427e40 03f0 03f0 [07] 01427e48 01f64 - (busy)
01429dc0 03f0 03f0 [07] 01429dc8 01f64 - (busy)
0142bd40 03f0 03f0 [07] 0142bd48 01f64 - (busy)
0142dcc0 03f0 03f0 [07] 0142dcc8 01f64 - (busy)
0142fc40 03f0 03f0 [07] 0142fc48 01f64 - (busy)
01431bc0 03f0 03f0 [07] 01431bc8 01f64 - (busy)
01433b40 03f0 03f0 [07] 01433b48 01f64 - (busy)
01435ac0 03f0 03f0 [07] 01435ac8 01f64 - (busy)
01437a40 03f0 03f0 [07] 01437a48 01f64 - (busy)
014399c0 03f0 03f0 [07] 014399c8 01f64 - (busy)
0143b940 03f0 03f0 [07] 0143b948 01f64 - (busy)
0143d8c0 03f0 03f0 [07] 0143d8c8 01f64 - (busy)
0143f840 03f0 03f0 [07] 0143f848 01f64 - (busy)
014417c0 03f0 03f0 [07] 014417c8 01f64 - (busy)
01443740 03f0 03f0 [07] 01443748 01f64 - (busy)
014456c0 03f0 03f0 [07] 014456c8 01f64 - (busy)
01447640 03f0 03f0 [07] 01447648 01f64 - (busy)
014495c0 03f0 03f0 [07] 014495c8 01f64 - (busy)
0144b540 03f0 03f0 [07] 0144b548 01f64 - (busy)
0144d4c0 03f0 03f0 [07] 0144d4c8 01f64 - (busy)
0144f440 03f0 03f0 [07] 0144f448 01f64 - (busy)
014513c0 03f0 03f0 [07] 014513c8 01f64 - (busy)
01453340 03f0 03f0 [07] 01453348 01f64 - (busy)
014552c0 03f0 03f0 [07] 014552c8 01f64 - (busy)
01457240 03f0 03f0 [07] 01457248 01f64 - (busy)
014591c0 03f0 03f0 [07] 014591c8 01f64 - (busy)
0145b140 03f0 03f0 [07] 0145b148 01f64 - (busy)
0145d0c0 03f0 03f0 [07] 0145d0c8 01f64 - (busy)
0145f040 03f0 03f0 [07] 0145f048 01f64 - (busy)
01460fc0 03f0 03f0 [07] 01460fc8 01f64 - (busy)
01462f40 03f0 03f0 [07] 01462f48 01f64 - (busy)
01464ec0 03f0 03f0 [07] 01464ec8 01f64 - (busy)
01466e40 03f0 03f0 [07] 01466e48 01f64 - (busy)
01468dc0 03f0 03f0 [07] 01468dc8 01f64 - (busy)
7.查看调用栈信息
可使用任一个UsrPtr的值来查询
!heap -p -a 0143d8c8
address 0143d8c8 found in
_HEAP @ 330000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
0143d8c0 03f0 0000 [07] 0143d8c8 01f64 - (busy)
Trace: 0025
7c96d6dc ntdll!RtlDebugAllocateHeap+0x000000e1
7c949d18 ntdll!RtlAllocateHeapSlowly+0x00000044
7c91b298 ntdll!RtlAllocateHeap+0x00000e64
102c103e MSVCR90D!_heap_alloc_base+0x0000005e
102cfd76 MSVCR90D!_heap_alloc_dbg_impl+0x000001f6
102cfb2f MSVCR90D!_nh_malloc_dbg_impl+0x0000001f
102cfadc MSVCR90D!_nh_malloc_dbg+0x0000002c
102db25b MSVCR90D!malloc+0x0000001b
102bd691 MSVCR90D!operator new+0x00000011
102bd71f MSVCR90D!operator new[]+0x0000000f
4113d8 Test2!AllocateMemory+0x00000028
41145c Test2!wmain+0x0000002c
411a08 Test2!__tmainCRTStartup+0x000001a8
41184f Test2!wmainCRTStartup+0x0000000f
7c816fd7 kernel32!BaseProcessStart+0x00000023
文章翻译和节选自:http://www.codeproject.com/Articles/31382/Memory-Leak-Detection-Using-Windbg
windbg 命令行参考
http://windbg.info/doc/1-common-cmds.html