使用Windbg定位内存泄露
来源:互联网 发布:网络模块的单词 编辑:程序博客网 时间:2024/05/16 18:40
在网上看了两篇文章,整理一下,大致内容如下:
场景一:运行Debug版本程序,用Windbg attach 上去,等程序退出时,基于内存泄露报告,定位内存泄露的位置。
首先使用windbg工具gflags.exe设置内存启动跟踪内存泄露进程的user stack启动方法就是运行下面指令<span style="BACKGROUND-COLOR: #ff6666">gflags.exe /i test.exe +ust</span><span style="BACKGROUND-COLOR: #ffffff"> <span style="color:#ff0000;">需要通过gflags.exe工具打开开关,才能调试内存泄露!</span></span>等价于HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options,命令“gflags.exe /i test.exe +ust”实际上就是在该路径下创建一个子键“test.exe”并创建一个名为GlobalFlag内容为0x00001000的REG_DWORD值。使用windbg加载test.exe,运行关闭时windbg中会提示内存泄露normal block at 0x026A5F98, 4000 bytes long.Data: < > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD Object dump complete.可以发现地址0x026A5F98就是内存泄漏的地址泄漏4000个字节通过!heap命令对该地址进行分析可以发现具体的调用堆栈0:000> <span style="BACKGROUND-COLOR: #ff99ff">!heap -p -a 0x026A5F98</span> address 026a5f98 found in _HEAP @ 14f0000 HEAP_ENTRY Size Prev Flags UserPtr UserSize - state 026a5f60 01fc 0000 [00] 026a5f78 00fc4 - (busy) 77a1b234 ntdll!RtlAllocateHeap+0x00000274 584d7743 MSVCR100D!_heap_alloc_base+0x00000053 584e5d8c MSVCR100D!_heap_alloc_dbg_impl+0x000001fc 584e5b2f MSVCR100D!_nh_malloc_dbg_impl+0x0000001f 584e5adc MSVCR100D!_nh_malloc_dbg+0x0000002c 584e5a91 MSVCR100D!_malloc_dbg+0x00000021 58694dd6 mfc100ud!operator new+0x00000026 58694e6a mfc100ud!operator new[]+0x0000001a 58694768 mfc100ud!operator new[]+0x00000018*** WARNING: Unable to verify checksum for SendMsgEx.exe 2a3c25 <span style="BACKGROUND-COLOR: #ff99ff">SendMsgEx!CSendMsgExDlg::Thread1Proc</span>+0x00000055 767c1174 kernel32!BaseThreadInitThunk+0x0000000e 779fb3f5 ntdll!__RtlUserThreadStart+0x00000070 779fb3c8 ntdll!_RtlUserThreadStart+0x0000001b可以发现内存泄漏的地址在CSendMsgExDlg::Thread1Proc这个地址里面调用了new[]导致内存泄漏DWORD WINAPI CSendMsgExDlg::Thread1Proc(__in LPVOID lpParameter){ INT *pVal = new INT[1000]; //..................}
结论:场景一适用于Debug版本程序,而且需要在程序退出时才能定位泄露。
场景二:程序运行一段时间,用Windbg attach上去,查看堆内存使用情况;detach 让程序继续运行;过一段时间再 attach,查看堆内存使用情况,与第一次对比,找到内存明显增长的堆。
我们开发的系统需要在客户的电脑上持续运行,可是客户报告在运行几天后,程序会占用越来越多的内存,最后会产生下面的两个错误使之不能继续:1. The application has no enough resource to display2. The application crash with a log like "memory allocation failed".怎么办?上windbg。准备工作Configure the symbol file path to the Microsoft symbol server “SRV*c:\symbols*http://msdl.microsoft.com/download/symbols”,也可以一个环境变量_NT_SYMBOL_PATH到系统路径下,省得每次配置它Add your program EXE/DLL PDB (program database) path to the symbol file path.(<span style="color:#ff0000;">设置PDB路径</span>)Configure the Operating System's flag to enable user stack trace for the process which has memory leaks.Gflags.exe -i excel.exe +ust(<span style="color:#ff0000;">和场景一一样,设置gflags.exe启动调试</span>)第一次记录让系统<span style="BACKGROUND-COLOR: #ff99ff">运行一段时间,用windbg attach 它的进程</span>,运行下面的命令0:025> <span style="BACKGROUND-COLOR: #ff99ff">!heap -s</span>LFH Key : 0xeaafe2e0Heap 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 LFH00260000 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 <span style="color:#000000;BACKGROUND-COLOR: #ff9900">04920000 00001002 1088 1012 1024 111 7 3 0 0 L </span>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(<span style="color:#ff0000;">windbg 和 应用程序detach, 如果不detach,程序被中断到调试状态,无法运行</span>)让它再运行一段时间,用windbg attach 它的进程,运行下面的命令0:025> !heap -sLFH Key : 0xeaafe2e0Heap 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 LFH00260000 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 <span style="BACKGROUND-COLOR: #ff6600">04920000 00001002 1088 3012 3024 511 7 3 0 0 L </span>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 <span style="BACKGROUND-COLOR: #ff6666">比较第一次和第二次,发现在0x04920000上的内存有明显的增长</span><span style="BACKGROUND-COLOR: #ff99ff">执行!heap -stat -h 04920000 去观察这段内存的详细情况</span>0:025> !heap -stat -h 04920000heap @ 04920000group-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)<span style="BACKGROUND-COLOR: #ff99ff">发现这段内存主要是由size=4的内存构成的</span>,而内存泄漏通常都是同一size的内存只分配,但没有释放引起的,所以,这个是值得高度怀疑的。<span style="BACKGROUND-COLOR: #ff99ff">执行!heap -flt s 4 去查进程中size=4的所有内存</span>,_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)<span style="BACKGROUND-COLOR: #ff99ff">然后执行!heap -p -a 0365e8f0 该内存分配时的堆栈。 这样就可以定位到内存泄露的根源了。</span>
结论:场景二比较试用于大部分情况,不需要是Debug版本,在现场调试,也不需要等待进程结束。
1 0
- 使用Windbg定位内存泄露
- WinDbg定位内存泄露
- windbg定位内存泄露
- WinDbg定位内存泄露
- Silverlight - 使用WinDbg定位内存泄露
- WinDbg 调试工具的使用(内存泄露)
- 使用windbg找内存泄露(memory leak)
- 使用WinDBG调试内存泄露的问题
- 使用windbg找内存泄露(memory leak)
- Windows调试——使用windbg查找内存泄露
- Windbg找应用程序内存泄露
- umdh windbg分析内存泄露
- 句柄泄露定位——使用windbg(可定位到具体代码)
- VC++内存泄露定位
- 内存泄露定位
- VC内存泄露定位
- VC++内存泄露定位
- 内存泄露定位
- Android 控件沿贝塞尔曲线运动(上)
- Java中的StringBuffer和数组Arrays以及常用类型的包装类
- HDU 1012.u Calculate e【水】【8月16】
- Android 开源框架Universal-Image-Loader完全解析(七)---从源代码分析Android-Universal-Image-Loader图片下载技巧
- 归并与归并排序算法
- 使用Windbg定位内存泄露
- Qt Style Sheets--简介
- CSS中背景图像
- Longest Common Prefix
- IIS 下部署WebAPI
- 读《How quitting...》有感
- Android自定义照相机实现(拍照、保存到SD卡,利用Bundle在Acitivity交换数据)
- 大牛们的博客收集
- css滤镜实现页面灰色黑白色效果代码