在 Windbg 下查找资源泄漏

参考:http://hi.baidu.com/xingxing/item/f834ffeae93fcf2d5b7cfb9a

 

有一个程序运行了一段时间后,内存占用呈线性增长,而且一直不降下来。

在 windbg 中对其动态调试,以确定原因。

先查看初始的堆状态:

 

0:007> !heap -s

NtGlobalFlag enables following debugging aids for new heaps:

    stack back traces

LFH Key                   : 0x34d21697

Termination on corruption : DISABLED

  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 

                    (k)     (k)    (k)     (k) length      blocks cont. heap 

-----------------------------------------------------------------------------

00230000 08000002    1024    544   1024     17    14     1    0      0   LFH

00010000 08008000      64      4     64      2     1     1    0      0      

01a30000 08001002    1088     80   1088      4     3     2    0      0   LFH

02d10000 08001002    1088    932   1088     98    38     2    0      0   LFH

02ca0000 08001002     256     60    256      1     4     1    0      0   LFH

02f10000 08001002     256    172    256    125     3     1    0      0      

04340000 08001002      64      4     64      2     1     1    0      0      

02e60000 08001002      64      4     64      2     1     1    0      0      

044c0000 08011002     256      4    256      1     2     1    0      0      

04690000 08001002     256      4    256      1     2     1    0      0      

-----------------------------------------------------------------------------

0:007> g

(504.c9c): Break instruction exception - code 80000003 (first chance)

eax=7ffd7000 ebx=00000000 ecx=00000000 edx=7709f125 esi=00000000 edi=00000000

eip=770340f0 esp=0317ff5c ebp=0317ff88 iopl=0         nv up ei pl zr na pe nc

cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246

ntdll!DbgBreakPoint:

770340f0 cc              int     3

运行了一小段时间后,再看一下,和之前的对比,发现某个堆增长明显:

0:007> !heap -s

NtGlobalFlag enables following debugging aids for new heaps:

    stack back traces

LFH Key                   : 0x34d21697

Termination on corruption : DISABLED

  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 

                    (k)     (k)    (k)     (k) length      blocks cont. heap 

-----------------------------------------------------------------------------

00230000 08000002    2048   1868   2048     17    17     2    0      0   LFH

00010000 08008000      64      4     64      2     1     1    0      0      

01a30000 08001002    1088     80   1088      4     3     2    0      0   LFH

02d10000 08001002    1088    980   1088    147    40     2    0      0   LFH

02ca0000 08001002     256     60    256      1     4     1    0      0   LFH

02f10000 08001002     256    172    256    125     3     1    0      0      

04340000 08001002      64      4     64      2     1     1    0      0      

02e60000 08001002      64      4     64      2     1     1    0      0      

044c0000 08011002     256      4    256      1     2     1    0      0      

04690000 08001002     256      4    256      1     2     1    0      0      

-----------------------------------------------------------------------------

统计一下这个堆里的内存分配情况,发现 1000 字节的内存分配占了 86.97%,目标就锁定它了。

0:007> !heap -stat -h 00230000

 heap @ 00230000

group-by: TOTSIZE max-display: 20

    size     #blocks     total     ( %) (percent of total busy bytes)

   1000 158 - 158000  (86.97)

    494 16 - 64b8  (1.59)

    20 2fd - 5fa0  (1.51)

    34 161 - 47b4  (1.13)

    3980 1 - 3980  (0.91)

    d0 30 - 2700  (0.62)

    1034 2 - 2068  (0.51)

    78 39 - 1ab8  (0.42)

    c88 2 - 1910  (0.40)

    10 131 - 1310  (0.30)

    11f8 1 - 11f8  (0.28)

    208 7 - e38  (0.22)

    248 6 - db0  (0.22)

    58 23 - c08  (0.19)

    400 3 - c00  (0.19)

    80 15 - a80  (0.17)

    a28 1 - a28  (0.16)

    960 1 - 960  (0.15)

    928 1 - 928  (0.14)

    22 39 - 792  (0.12)

看一下都是哪些堆申请的:

0:007> !heap -flt s 1000

    _HEAP @ 230000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        0027b810 0203 0000  [00]   0027b828    01000 - (busy)

        0027c900 0203 0203  [00]   0027c918    01000 - (busy)

        00285670 0203 0203  [00]   00285688    01000 - (busy)

        00286688 0203 0203  [00]   002866a0    01000 - (busy)

        002876a0 0203 0203  [00]   002876b8    01000 - (busy)

        002886b8 0203 0203  [00]   002886d0    01000 - (busy)

        002896d0 0203 0203  [00]   002896e8    01000 - (busy)

        0028a6e8 0203 0203  [00]   0028a700    01000 - (busy)

        0028bf10 0203 0203  [00]   0028bf28    01000 - (busy)

        0028cf28 0203 0203  [00]   0028cf40    01000 - (busy)

        0028df40 0203 0203  [00]   0028df58    01000 - (busy)

....

....

....

 

 

    _HEAP @ 10000

    _HEAP @ 1a30000

    _HEAP @ 2d10000

    _HEAP @ 2ca0000

    _HEAP @ 2f10000

    _HEAP @ 4340000

    _HEAP @ 2e60000

    _HEAP @ 44c0000

    _HEAP @ 4690000

随便挑几个地址看一下调用栈:

0:007> !heap -p -a 0303aec0

    address 0303aec0 found in

    _HEAP @ 230000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        0303aec0 0221 0000  [00]   0303aed8    01000 - (busy)

        7707dd6c ntdll!RtlAllocateHeap+0x00000274

        7541f947 KERNELBASE!FindNextFileW+0x00000090

        ...

        ...

        771a3c45 kernel32!BaseThreadInitThunk+0x0000000e

        770637f5 ntdll!__RtlUserThreadStart+0x00000070

        770637c8 ntdll!_RtlUserThreadStart+0x0000001b

 再结合源代码,确定是 FindNextFileW 遍历文件完成之后,没有调用 FindClose 关闭句柄,导致资源没有被释放。

 在使用上面的方法调试之前,要先打开 Create user mode stack trace database

 

0:004> !gflag +ust

Current NtGlobalFlag contents: 0x00001000

    ust - Create user mode stack trace database

你可能感兴趣的:(DB)