基于windbg的内存泄露分析

可以使用windbg附带的工具gflags.exe可以对堆调用的过程进行跟踪,对内存泄露的排查有很大的帮助:在windbg程序目录下有个gflags.exe,运行后设置:



运行CMD.EXE,输入"D:\Debugging Tools for Windows (x86)\gflags.exe" /i test.exe +ust,如果设置成功则显示:


设置完成后通过堆分配的地址就能通过!heap命令查看进程分配堆时的调用栈,可以通过crt提供的_CrtDumpMemoryLeaks()函数来打印堆分配的地址,打印的内容如下,然后通过!heap -p -a 003bbab0命令即可查看调用栈。

如果没有使用CRT的函数打印堆地址,可以通过下面的方法筛选出堆地址:

让系统运行一段时间,用windbg attach 它的进程,运行下面的命令

0:025> !heap -s
LFH Key                   : 0xeaafe2e0
Heap     Flags   Reserv Commit Virt   Free List   UCR Virt Lock Fast
                    (k)     (k)    (k)     (k) length      blocks cont. heap
-----------------------------------------------------------------------------
00160000 00000002   32768 28204 28492   1460   239    19    0      f   LFH
00260000 00001002      64     40     40      3     1     1    0      0   L 
00270000 00008000      64     12     12     10     1     1    0      0     
004e0000 00000002      64      8      8      0     0     1    0      0   L 
00030000 00001002    1088     72     72      9     2     1    0      0   L 
00480000 00001002    7232   3444   3444     36     5     2    0      0   L 
004c0000 00001002    1088    252    252      5     1     1    0      0   L 
004d0000 00001002      64     12     12      4     1     1    0      0   L 
01060000 00001002      64     16     16      2     2     1    0      0   L 
01120000 00000002    1024     24     24      0     0     1    0      0   L 
010b0000 00001002     256     32     32      0     0     1    0      0   L 
01660000 00001002    3136   2796   2828    377    13     7    0      0   L 
    External fragmentation 13 % (13 free blocks)
01680000 00001002      64     32     32      3     0     1    0      0   L 
01690000 00041002     256     12     12      0     0     1    0      0   L 
01790000 00001003     256    104    116     60     9     3    0    bad     
017d0000 00001003     256      4      4      2     1     1    0    bad     
01810000 00001003     256      4      4      2     1     1    0    bad     
030d0000 00001003     256      4      4      2     1     1    0    bad     
03110000 00001003     256      4      4      2     1     1    0    bad     
01850000 00001002      64     20     20      2     1     1    0      0   L 
03560000 00001002    1280    664    776     22     7     4    0      0   L 
04780000 00001003     256      8      8      2     1     1    0    bad     
047c0000 00001003     256      4      4      2     1     1    0    bad     
04800000 00001003     256      4      4      2     1     1    0    bad     
04840000 00001003     256      4      4      2     1     1    0    bad     
04880000 00001003     256      4      4      2     1     1    0    bad     
048e0000 00001002     256     16     16      4     1     1    0      0   L 
04920000 00001002    1088   1012   1024    111     7     3    0      0   L 
04930000 00001002    3136    940    940    153     9     2    0     8d   L 
04ce0000 00001002      64     16     16      0     0     1    0      0   L 
04cf0000 00001002    1088    192    192      6     2     1    0      0   L 
05850000 00001002      64     28     28      1     1     1    0      0   L 
05de0000 00001002      64     12     12      3     1     1    0      0   L 

第二次记录

Detatch the windbg from the excel process

让它再运行一段时间,用windbg attach 它的进程,运行下面的命令

0:025> !heap -s
LFH Key                   : 0xeaafe2e0
Heap     Flags   Reserv Commit Virt   Free List   UCR Virt Lock Fast
                    (k)     (k)    (k)     (k) length      blocks cont. heap
-----------------------------------------------------------------------------
00160000 00000002   32768 28204 28492   1460   239    19    0      f   LFH
00260000 00001002      64     40     40      3     1     1    0      0   L 
00270000 00008000      64     12     12     10     1     1    0      0     
004e0000 00000002      64      8      8      0     0     1    0      0   L 
00030000 00001002    1088     72     72      9     2     1    0      0   L 
00480000 00001002    7232   3444   3444     36     5     2    0      0   L 
004c0000 00001002    1088    252    252      5     1     1    0      0   L 
004d0000 00001002      64     12     12      4     1     1    0      0   L 
01060000 00001002      64     16     16      2     2     1    0      0   L 
01120000 00000002    1024     24     24      0     0     1    0      0   L 
010b0000 00001002     256     32     32      0     0     1    0      0   L 
01660000 00001002    3136   2796   2828    377    13     7    0      0   L 
    External fragmentation 13 % (13 free blocks)
01680000 00001002      64     32     32      3     0     1    0      0   L 
01690000 00041002     256     12     12      0     0     1    0      0   L 
01790000 00001003     256    104    116     60     9     3    0    bad     
017d0000 00001003     256      4      4      2     1     1    0    bad     
01810000 00001003     256      4      4      2     1     1    0    bad     
030d0000 00001003     256      4      4      2     1     1    0    bad     
03110000 00001003     256      4      4      2     1     1    0    bad     
01850000 00001002      64     20     20      2     1     1    0      0   L 
03560000 00001002    1280    664    776     22     7     4    0      0   L 
04780000 00001003     256      8      8      2     1     1    0    bad     
047c0000 00001003     256      4      4      2     1     1    0    bad     
04800000 00001003     256      4      4      2     1     1    0    bad     
04840000 00001003     256      4      4      2     1     1    0    bad     
04880000 00001003     256      4      4      2     1     1    0    bad     
048e0000 00001002     256     16     16      4     1     1    0      0   L 
04920000 00001002    1088   3012   3024    511     7     3    0      0   L 
04930000 00001002    3136    940    940    153     9     2    0     8d   L 
04ce0000 00001002      64     16     16      0     0     1    0      0   L 
04cf0000 00001002    1088    192    192      6     2     1    0      0   L 
05850000 00001002      64     28     28      1     1     1    0      0   L 
05de0000 00001002      64     12     12      3     1     1    0      0   L 

比较第一次和第二次,发现在0x04920000上的内存有明显的增长

执行!heap -stat -h 04920000 去观察这段内存的详细情况

0:025> !heap -stat -h 04920000
heap @ 04920000
group-by: TOTSIZE max-display: 20
    size     #blocks     total     ( %) (percent of total busy bytes)
     4 21a29 - 82cd0 (94.77)
    d0 2a - 2220 (1.06)
    20 cd - 19a0 (0.79)
    90 2d - 1950 (0.78)
    be0 2 - 17c0 (0.74)
    e0 1b - 17a0 (0.73)
    f0 19 - 1770 (0.73)
    1f0 b - 1550 (0.66)
    200 a - 1400 (0.62)
    40 4f - 13c0 (0.61)
    240 7 - fc0 (0.49)
    bd0 1 - bd0 (0.37)
发现这段内存主要是由size=4的内存构成的,而内存泄漏通常都是同一size的内存只分配,但没有释放引起的,所以,这个是值得高度怀疑的。

执行!heap -flt s 4 去查进程中size=4的所有内存,

_HEAP @ 04920000 
        03659ab8 0002 0002 [01]   03659ac0    00004 - (busy)
        03659ac8 0003 0002 [01]   03659ad0    00004 - (busy)
        0365e8e8 0002 0003 [01]   0365e8f0    00004 - (busy)
        0f2b9fe8 0003 0002 [11]   0f2b9ff0    00004 - (busy)
        0f2d9760 0003 0003 [01]   0f2d9768    00004 - (busy)
        0f2dcc20 0002 0003 [01]   0f2dcc28    00004 - (busy)
        0f2dcc50 0002 0002 [01]   0f2dcc58    00004 - (busy)
        0f2dd790 0002 0002 [01]   0f2dd798    00004 - (busy)
        0f2dd7c0 0002 0002 [01]   0f2dd7c8    00004 - (busy)
        0f2de260 0002 0002 [01]   0f2de268    00004 - (busy)
        0f2de290 0002 0002 [01]   0f2de298    00004 - (busy)
        0f2de2a0 0003 0002 [01]   0f2de2a8    00004 - (busy)
        0f2df740 0002 0003 [01]   0f2df748    00004 - (busy)
        0f2e0270 0002 0002 [01]   0f2e0278    00004 - (busy)
        0f2e02a0 0002 0002 [01]   0f2e02a8    00004 - (busy)
        0f2e02e0 0003 0002 [01]   0f2e02e8    00004 - (busy)
        0f2e1270 0002 0003 [01]   0f2e1278    00004 - (busy)
        0f2e1ce0 0002 0002 [01]   0f2e1ce8    00004 - (busy)
        0f2e1d10 0002 0002 [01]   0f2e1d18    00004 - (busy)
        0f2e27d0 0002 0002 [01]   0f2e27d8    00004 - (busy)
        0f2e2800 0002 0002 [01]   0f2e2808    00004 - (busy)
        0f2e2cc0 0002 0002 [01]   0f2e2cc8    00004 - (busy)
        0f2e2cf0 0002 0002 [01]   0f2e2cf8    00004 - (busy)
        0f2e3340 0003 0002 [01]   0f2e3348    00004 - (busy)
        0f2e3d20 0002 0003 [01]   0f2e3d28    00004 - (busy)
        0f2e4890 0002 0002 [01]   0f2e4898    00004 - (busy)
        0f2e48c0 0003 0002 [01]   0f2e48c8    00004 - (busy)

然后执行!heap -p -a 0365e8f0 该内存分配时的堆栈。 这样就可以定位到内存泄露的根源了。

内存泄漏是指在程序运行过程中,分配的内存没有被正确释放,导致内存占用不断增加,最终耗尽系统资源。使用Windbg可以帮助我们检测和定位内存泄漏问题。Windbg是微软提供的Windows下强大的调试工具,可以分析多种软件异常问题。使用Windbg监测内存泄漏的一般步骤包括以下几个步骤:首先,我们需要在程序运行时使用Windbg附加到目标进程;然后,通过Windbg的命令和扩展插件来监测和分析内存使用情况;最后,根据Windbg的输出结果来定位内存泄漏的具体位置和原因。需要注意的是,Windbg只能监测两个时间点的申请堆内存的变化量,并没有统计释放的堆内存,因此在分析结果时需要结合代码将其他几项过滤掉,最终确定发生内存泄漏的那一项。\[1\]\[2\]如果你想了解更多关于使用Windbg监测内存泄漏的详细步骤和技巧,可以参考相关的专栏文章列表,如VC++常用功能开发汇总和C++软件异常排查从入门到精通系列教程。\[3\] #### 引用[.reference_title] - *1* *2* *3* [使用Windbg定位Windows C++程序中的内存泄漏](https://blog.csdn.net/chenlycly/article/details/121295720)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值