zoukankan      html  css  js  c++  java
  • 使用windbg检测内存泄漏

    缘起

    作为C++程序员,检测内存泄漏是非常痛苦的事情。尤其是看着程序的内存在一直增长,你却无能为力。此时,windbg可以用来检测内存泄漏。


    配置windbg

    1.  配置symbol文件路径: “SRV*d:symbols*http://msdl.microsoft.com/download/symbols”.
    2.  增加测试程序test.exe的pdb 文件到symbol文件路径
    3.  采用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

     heap@ 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

    11.  至此,我们可以定位程序中memory leak的函数了。


    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:WindowsSystem32wshtcpip.dll

    741f0000 7422c000   mswsock   (export symbols)      C:Windowssystem32mswsock.dll      

    74240000 74253000   dwmapi    (export symbols)      C:Windowssystem32dwmapi.dll

    74260000 742e0000   UxTheme   (export symbols)      C:Windowssystem32UxTheme.dll

    742e0000 742e9000   VERSION   (export symbols)      C:Windowssystem32VERSION.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

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

    Ref

    http://www.codeproject.com/Articles/31382/Memory-Leak-Detection-Using-Windbg

    http://stackoverflow.com/questions/6941862/windbg-heap-command-not-working

    http://support.microsoft.com/kb/959207

  • 相关阅读:
    C++-蓝桥杯-颠倒的价牌[2013真题][水题][模拟]
    C++-蓝桥杯-振兴中华[2013真题][水题][dp/递归]
    C++-蓝桥杯-排它平方数[2013][水题][枚举]
    C++-蓝桥杯-高斯日记[2013真题][水题][枚举模拟]
    C++-蓝桥杯-购物清单[2017真题][水题][文件输入]
    C++-蓝桥杯-九宫幻方[暴力搜索][无剪枝]
    C++-LUOGU3834 可持久化线段树(主席树)[模板]
    BASIC-2 01字串
    【掌大】关注回复
    【掌大】纸飞机
  • 原文地址:https://www.cnblogs.com/lidabo/p/14363817.html
Copyright © 2011-2022 走看看