如何找內存泄露

先寫一段這樣的程序:
#include "stdafx.h"
#include <windows.h>windows

void AllocateMemory() 

     int* a = new int[2000]; 
     for(int i=0;i<2000;i++)
  {
  *a=0;
  a++;
  }
     Sleep(1); 
}操作系統

int _tmain(int argc, _TCHAR* argv[])
{   while(1) 
     { 
        AllocateMemory(); 
     } 
     return 0; 
}3d

而後打開windbg,attach上這個程序(非侵入),在DbgBreakPoint中止
輸入命令:!heap -s
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                    (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
00150000 00000002    1024     16     16      2     1     1    0      0   L  
00250000 00001002      64     24     24     15     1     1    0      0   L  
00260000 00008000      64     12     12     10     1     1    0      0      
00380000 00001002      64     16     16      1     1     1    0      0   L  
003a0000 00001002  130112  73260  73260     33     7     1    0      0   L  
-----------------------------------------------------------------------------進程

而後讓它繼續運行,輸入g
過一會再將它break.內存

0:001> !heap -s
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                    (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
00150000 00000002    1024     16     16      2     1     1    0      0   L  
00250000 00001002      64     24     24     15     1     1    0      0   L  
00260000 00008000      64     12     12     10     1     1    0      0      
00380000 00001002      64     16     16      1     1     1    0      0   L  
003a0000 00001002  130112  97020  97020     35     7     1    0      0   L  
-----------------------------------------------------------------------------it

而後再g,過一會再break.
0:001> !heap -s
  Heap     Flags   Reserv  Commit  Virt   Free  List   UCR  Virt  Lock  Fast 
                    (k)     (k)    (k)     (k) length      blocks cont. heap 
-----------------------------------------------------------------------------
00150000 00000002    1024     16     16      2     1     1    0      0   L  
00250000 00001002      64     24     24     15     1     1    0      0   L  
00260000 00008000      64     12     12     10     1     1    0      0      
00380000 00001002      64     16     16      1     1     1    0      0   L  
003a0000 00001002  261184 179204 179204     35     8     1    0      0   L  
-----------------------------------------------------------------------------ast

注意看003a0000地址,它申請的內存和使用的內存都一直再長。 說明這個堆地址有泄漏。配置

對這個堆作個統計:List

!heap -stat -h 003a0000 
 heap @ 003a0000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
    1f40 597c - aec6300  (99.99)
    800 2 - 1000  (0.00)
    48a 1 - 48a  (0.00)
    214 2 - 428  (0.00)
    245 1 - 245  (0.00)
    220 1 - 220  (0.00)
    94 2 - 128  (0.00)
    72 2 - e4  (0.00)
    c8 1 - c8  (0.00)
    54 2 - a8  (0.00)
    90 1 - 90  (0.00)
    48 2 - 90  (0.00)
    8e 1 - 8e  (0.00)
    88 1 - 88  (0.00)
    44 2 - 88  (0.00)
    80 1 - 80  (0.00)
    2a 3 - 7e  (0.00)
    76 1 - 76  (0.00)
    39 2 - 72  (0.00)
    26 3 - 72  (0.00)
發現這個堆中,大小爲1f40的內存塊最多。
根據大小過濾下這個
!heap -flt s 1f40
    _HEAP @ 150000
    _HEAP @ 250000
    _HEAP @ 260000
    _HEAP @ 380000
    _HEAP @ 3a0000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        003a5c70 03e9 0000  [01]   003a5c78    01f40 - (busy)
        003a7bb8 03e9 03e9  [01]   003a7bc0    01f40 - (busy)
        003a9b00 03e9 03e9  [01]   003a9b08    01f40 - (busy)
        003aba48 03e9 03e9  [01]   003aba50    01f40 - (busy)
        003ad990 03e9 03e9  [01]   003ad998    01f40 - (busy)
        00410040 03e9 03e9  [01]   00410048    01f40 - (busy)
        00411f88 03e9 03e9  [01]   00411f90    01f40 - (busy)
        00413ed0 03e9 03e9  [01]   00413ed8    01f40 - (busy)
        00415e18 03e9 03e9  [01]   00415e20    01f40 - (busy)
        00417d60 03e9 03e9  [01]   00417d68    01f40 - (busy)
        00419ca8 03e9 03e9  [01]   00419cb0    01f40 - (busy)
        0041bbf0 03e9 03e9  [01]   0041bbf8    01f40 - (busy)
        0041db38 03e9 03e9  [01]   0041db40    01f40 - (busy)
        0041fa80 03e9 03e9  [01]   0041fa88    01f40 - (busy)
        004219c8 03e9 03e9  [01]   004219d0    01f40 - (busy)
        00423910 03e9 03e9  [01]   00423918    01f40 - (busy)
        00425858 03e9 03e9  [01]   00425860    01f40 - (busy)
        004277a0 03e9 03e9  [01]   004277a8    01f40 - (busy)
        004296e8 03e9 03e9  [01]   004296f0    01f40 - (busy)
        0042b630 03e9 03e9  [01]   0042b638    01f40 - (busy)
        ... ...bug

明顯能夠看到3a0000中有很多這種內存塊。取一個UserPtr,調用!heap -p -a UsrPtr

這樣能夠顯示出這個塊的調用棧。
0:001> !heap -p -a 0b2fe198
    address 0b2fe198 found in
    _HEAP @ 3a0000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0b2fe190 03e9 0000  [01]   0b2fe198    01f40 - (busy)

這裏什麼都沒有,固然你須要配置操做系統標誌來啓動跟蹤內存泄露進程的user stack。
啓動方法就是運行下面指令gflags.exe /i Testleak.exe +ust。

這樣運行上面命令就有!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這樣的效果     這樣泄露的位置就很清楚的找到了

相關文章
相關標籤/搜索