使用windbg检测内存泄漏

摘要:
此时,可以使用windg来检测内存泄漏。配置windag:配置符号文件路径:“SRV*d:符号*http://msdl.microsoft.com/download/symbols“从测试程序test.exe的pdb文件到符号文件的路径是Gflags.exe,用户堆栈跟踪添加到测试程序leak.exe.Gflags。exe/test。exe+ust开始调试:1.打开windg,单击“附加到进程”,然后装载测试exeheap–sNtGlobalFlag启用以下新堆的调试帮助:HeapFlagsServCommitVirtFreeListUCRVirtLockFastlengthblockscot。堆-------------------------------------------------------------------------------------------------------------------02e90000800000021024440810243116100LFH02e0000008001008136108818420LFH04870000800100225620256121000300008001002313613083136136136136136192333300LFH0484000008001002641264210004750000080010010010000225642561100057400000002256425602100------------------------------------------------------------------------------3.让程序继续运行一段时间…heap–sNtGlobalFlagenables遵循新堆的调试帮助:HeapFlagsServCommitVirtFreeListUCRVirtLockFastlengthblockscot。堆-------------------------------------------------------------------------------------------------------------------02e900008000002102440810243216100LFH02e0000008002108110881361088184200LFH04870000800100225620256121000300008001002313617523136143300LFH0484000008001002641264210004750000080010010010010000225642561100057400000002256425602100------------------------------------------------------------------------------5.比较两个堆然后找到堆分配最多的堆,并记住堆地址。

缘起

作为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

免责声明:文章转载自《使用windbg检测内存泄漏》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇super方法flask 框架 练习下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

windbg

http://www.codemachine.com/article_x64deepdive.html https://sites.google.com/site/jozsefbekes/Home/windows-programming/windbg http://www.codeproject.com/Articles/Toby-Opferman#Art...

windbg调试C#代码(一)

用windbg调试C#代码是比较麻烦的,因为windbg是针对OS层级的,而C#被CLR隔了一层,很多原生的命令如查看局部变量dv、查看变量类型dt等在CLR的环境中都不能用了。必须使用针对CLR的扩展命令,比如sos、psscor2中的命令。下面以一个最简单的WPF程序来说明调试的典型步骤,以及典型的坑。 1、用正确版本的windbg、加载正确版本的扩展...

windbg源码驱动调试 + 无源码驱动调试

windbg源码驱动调试   环境信息 虚拟机:win7 32位 windbg:6.12(版本不存在太大影响) 设置过程 windbg与虚拟机连接:链接 配置windbg 配置好双机调试后,点击windbg菜单栏的debug->Break产生中断,控制权交给windbg 中断产生后,点击File->Open Sourse File(Ct...

用windbg分析一个dead lock的问题

难得Winform项目中碰到dead lock,记录一下。 QA报告说,有时候晚上跑完自动化脚本,第二天早上来发现系统hang在屏保界面没反应,从日志看也没有报错。这种属于很少才会发生,也不知道怎么重现,但是很严重的bug,于是抓个dump来研究一下。 # Windbg加载dump文件后的一些文件信息 Microsoft (R) Windows Debu...

windbg笔记

数据结构 Module EEClass MD(Method Desc) MT(Method desc Table) Object 基本命令 ~*e!clrstack 查看所有持有和等待锁的线程(的下一条要执行的代码) k 观察非托管堆栈 x <模块名>!*<函数名>* 查看符号 lm -f 显示已经载入的模块及其完整路径 sx...

利用WinDbg找出程序崩溃的代码行号

之前碰到论坛里有几个好友,说程序不时的崩溃,什么xxoo不能read的! 如果光要是这个内存地址,估计你会疯掉~~所以分享一下基本的调试技巧,需要准备的工具有WinDbg + VC6.0,下面是自己整理的一份自动生成DUMP文件的源代码,只需要添加到工程即可,源代码如下:MiniDump.hMiniDump.cpp<具体请参考附件SRC中,太大就不贴...