使用windbg检测内存泄漏[有源码和截图]
使用windbg检测内存泄漏[有源码和截图]
一、基本步骤
配置环境windbg:
配置symbol文件路径: “SRV*d:\symbols*http://msdl.microsoft.com/download/symbols”.
增加测试程序test.exe的pdb 文件到symbol文件路径
采用Gflags.exe,增加userstack trace到测试程序leak.exe中。 gflags.exe /i test.exe +ust
开始调试:
1. 打开windbg,点击’attach to process’,挂载上test.exe。
2. 敲入命令>!heap –s 【抓取堆快照】
NtGlobalFlag enables following debuggingaids for new heaps:
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
02e90000 08000002 1024 408 1024 31 16 1 0 0 LFH
02e00000 08001002 1088 136 1088 18 4 2 0 0 LFH
04870000 08001002 256 20 256 1 2 1 0 0
00300000 08001002 3136 1308 3136 19 23 3 0 0 LFH
04840000 08001002 64 12 64 3 2 1 0 0
04750000 08001002 256 4 256 1 1 1 0 0
05740000 08001002 256 4 256 0 2 1 0 0
-----------------------------------------------------------------------------
3. 让程序接着运行一段时间。
4. 再次输入敲入命令>!heap –s 【找不同】
NtGlobalFlag enables following debuggingaids for new heaps:
Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
(k) (k) (k) (k) length blocks cont. heap
-----------------------------------------------------------------------------
02e90000 08000002 1024 408 1024 32 16 1 0 0 LFH
02e00000 08001002 1088 136 1088 18 4 2 0 0 LFH
04870000 08001002 256 20 256 1 2 1 0 0
00300000 08001002 3136 1752 3136 14 23 3 0 0 LFH
04840000 08001002 64 12 64 3 2 1 0 0
04750000 08001002 256 4 256 1 1 1 0 0
05740000 08001002 256 4 256 0 2 1 0 0
-----------------------------------------------------------------------------
5. 比较两次heap的分配情况,然后找出堆分配最多的heap,记住堆地址。
6. 输入命令 0:015> !heap -stat -h 00300000 【查看堆中的分布情况】
[email protected] 00300000
group-by: TOTSIZE max-display: 20
size #blocks total ( %) (percent of total busy bytes)
16a8 32 - 46cd0 (27.90)
800 85 - 42800 (26.20)
14 34dc - 42130 (26.03)
105b8 1 - 105b8 (6.44)
190 32 - 4e20 (1.92)
2012 2 - 4024 (1.58)
4000 1 - 4000 (1.58)
36b0 1 - 36b0 (1.35)
214 14 - 2990 (1.02)
7. 找到分配次数最多的内存堆,记住这个堆的大小,在这个例子中,我们找到分配次数是34dc,堆的大小是14.
8. 此时,输入命令 0:015> !heap -flt s 14 【查看固定大小的分配句柄】
_HEAP @ 2e90000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
02eb33e0 0006 0000 [00] 02eb33f8 00014 - (busy)
mfc90u!CShellWrapper::`vftable'
02eb6ff0 0006 0006 [00] 02eb7008 00014 - (busy)
mfc90u!CShellWrapper::`vftable'
02eb83a8 0006 0006 [00] 02eb83c0 00014 - (busy)
9. 查找任意一个分配该大小堆的地址,02eb7008
10. 输入命令0:015> !heap -p -a 02eb7008 【查看分配时的情况】
address 06aae780 found in
_HEAP @ 300000
HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
06aae768 0006 0000 [00] 06aae780 00014 - (busy)
7719ddbd ntdll!RtlAllocateHeap+0x00000274
747c3a58 MSVCR90!malloc+0x00000079
460879 test!CUDPThread::Run+0x00000689
4601dc test!CUDPThread::Main+0x0000003c
74783433 MSVCR90!_callthreadstartex+0x0000001b
747834c7 MSVCR90!_threadstartex+0x00000069
至此,我们可以定位程序中memory leak的函数了。
二、补充一个实例[win 7 + 64]
1 code
2 调试步骤
3 找不同之后的变化堆分布
4、查看分配时的具体信息
三、备注&Issues:
1. Error: Symbol can not be found.
0:015> .reload /f 强制加载module
Reloading current modules
......
…
0:015> lm 查看module加载情况
start end module name
741e0000 741e5000 wshtcpip (export symbols) C:\Windows\System32\wshtcpip.dll
741f0000 7422c000 mswsock (export symbols) C:\Windows\system32\mswsock.dll
74240000 74253000 dwmapi (export symbols) C:\Windows\system32\dwmapi.dll
74260000 742e0000 UxTheme (export symbols) C:\Windows\system32\UxTheme.dll
742e0000 742e9000 VERSION (export symbols) C:\Windows\system32\VERSION.dll
2. Heap – Invalid type information
0:015> !heap -s
*************************************************************************
*** Either you specified an unqualified symbol, or your debugger ***
*** doesn't have full symbol information. Unqualified symbol ***
*** resolution is turned off by default. Please either specify a ***
*** fully qualified symbol module!symbolname, or enable resolution ***
*** of unqualified symbols by typing ".symopt- 100". Notethat ***
*** enabling unqualified symbol resolution with network symbol ***
*** server shares in the symbol path may cause the debugger to ***
*** appear to hang for long periods of time when an incorrect ***
*** symbol name is typed or the network symbol server is down. ***
*** For some commands to work properly, your symbol path ***
*** must point to .pdb files that have full type information. ***
*** Certain .pdb files (such as the public OS symbols) do not ***
*** contain the required information. Contact the group that ***
*** provided you with these symbols if you need this command to ***
*** Type referenced: ntdll!_HEAP_ENTRY ***
*************************************************************************
Invalid type information
解决方法:
0:015> .symfix
0:015> .reload
Reloading current modules
................