使用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

使用windbg检测内存泄漏[有源码和截图]

2 调试步骤

使用windbg检测内存泄漏[有源码和截图]

3 找不同之后的变化堆分布

使用windbg检测内存泄漏[有源码和截图]

4、查看分配时的具体信息

使用windbg检测内存泄漏[有源码和截图]

三、备注&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

................