(Windbg调试七)c++内存泄漏问题定位

c++内存泄漏问题定位

     内存泄漏指的是直接操作内存分配构造函数(例如new,malloc,HeapAlloc)来获得堆内存后,但是没有释放而导致的泄漏问题。我们的行情服务器是一个长期运行在客户服务器上的应用程序,如果存在内存泄漏,那么当内存增长到某个值时,会极大地影响当前机器的性能,直至影响我们的行情服务程序,甚至由于内存已不够而导致的程序崩溃。因此我们需要掌握内存泄漏问题的基本调试技巧,本文对windbg调试内存泄漏问题做一个简单的介绍。
     以下面这个代码为例:

#include <iostream>
#include <windows.h>

int main()
{
	do 
	{
		char *p = new char[1024];
		Sleep(1);
	} while (1);
	
    std::cout << "Hello World!\n"; 
}

先进行windbg环境的配置:
1)配置windows符号服务器SRVd:\symbolshttp://msdl.microsoft.com/download/symbols
2)将当前程序的pdb文件路径加入到Windbg的Symbol File Path路径中
3)配置操作系统的标志,以便为内存泄漏的进程启用用户堆栈跟踪。可以通过安装Windbg自带的gflags.exe程序,通过命令“gflags.exe -i 20190718.exe +ust”来完成,20190718.exe是程序名(不用带路径,只用输入程序名即可)
在这里插入图片描述

准备工作完成后,开始进行一步步来调试: 1, 启动20190718.exe程序,使用Windbg的Attach To Process附加上去(或者通过Open Excutable直接打开)

2, 附加进程后,输入“!heap –s”命令。-s代表统计信息,可以查看当前进程的所有堆分配信息:
在这里插入图片描述
此时只有一个堆02d40000(这个堆是CRT堆)。

3, F5让程序继续运行一会儿,然后中断(Windbg-Debug-Break菜单),再次输入“!heap –s”命令:
在这里插入图片描述
可以看到02d40000堆上分配的内存有增加。

4, 再输入“!heap -stat -h 02d40000”命令,查看正在增长的堆的堆统计信息:
在这里插入图片描述
-stat命令能够给出关于一个或者多个堆的使用统计信息,包括分配内存的大小,这个大小的堆块的个数以及总共的大小,最后是当前处于“busy”(占用)状态的堆块所占百分比。默认情况下,-stat按照总量大小来排序。

上面的快照显示正在分配的400(十六进制)大小的堆块有0x5acf个,且堆块所占百分比达到了99.77%,这些数据使我们推测大小为400(十六进制)bytes的内存存在泄漏的可能(也刚好是代码中分配的1024字节)。


5, 输入“!heap –flt s 400”,查看堆上所有大小为400的blocks信息:
在这里插入图片描述

6, 输入“!heap –p –a UserPtr”命令,UserPtr为上面的任何一个地址,比如!heap -p -a 047b8e70,显示地址047b8e70的调用堆栈信息:
在这里插入图片描述
从调用堆栈中可以看到,!main+0x0000001a地址处的代码可能导致内存泄漏。


7, 输入“lsa !main+0x0000001a”转到具体代码处:
在这里插入图片描述

参考文献:
1,《Windows高级调试》第九章第五节
2, https://www.codeproject.com/Articles/31382/Memory-Leak-Detection-Using-Windbg

发布了78 篇原创文章 · 获赞 79 · 访问量 6万+

猜你喜欢

转载自blog.csdn.net/bajianxiaofendui/article/details/96590223