如何检查内存泄露并进行定位

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/patkritLee/article/details/51771739
1. 定义:应用程序分配某段内存后,由于设计错误,失去了对该段内存的控制,因而造成了内存的浪费
2. 对于C和C++这种没有Garbage Collection 的语言来讲,我们主要关注两种类型的内存泄漏:

   堆内存泄漏(Heap leak)。对内存指的是程序运行中根据需要分配通过malloc,realloc new等从堆中分配的一块内存,再是完成后必须通过调用对应的 free或者delete 删掉。如果程序的设计的错误导致这部分内存没有被释放,那么此后这块内存将不会被使用,就会产生Heap Leak. 

  系统资源泄露(Resource Leak).主要指程序使用系统分配的资源比如 Bitmap,handle ,SOCKET等没有使用相应的函数释放掉,导致系统资源的浪费,严重可导致系统效能降低,系统运行不稳定。  
或者:
  1. 分配完内存之后忘了回收;
  2. 程序Code有问题,造成没有办法回收;
  3. 某些API函数操作不正确,造成内存泄漏。
3. 定位

在工作中,遇到OOM,你首先要确定他是由于什么原因引起的?是因为堆空间设置太小引起还是因为内存泄露引起。实际上,内存泄露的问题可以通过增大堆空间暂时得到解决,但是他不是长久之计。

  我们可以通过对应用访问峰值时堆空间利用率的分析来确定应用是否存在内存泄露,比如我们可以用JMeter来进行压力测试,我们每次对应用加压1000,一共加压10次,第一次峰值时堆使用了100M,第二次峰值时使用了200M,第三次峰值时使用了300M….那这样我们基本可以确定应用存在内存泄露。因为正常情况下,每次峰值时的堆占用率应该是差不多的,而上面的例子每次峰值时数据出入都比较大,而且是逐步增加,这不是一个正常的现象。

  观察内存的使用情况,你可以使用JConsole或者VisualVM等工具

4.Windbg手动分析内存泄露

4.1全局标志设置,参照3.1

4.2.Windbg调试泄露

开启memoryleak.exe程序,windbg attach到该进程

命令:!heap –s查看当前进程运行的所有堆的情况

然后F5让程序运行一段时间或者内存有明显的增加时再次通过!heap –s查看当前堆的变化

如下图

通过对比前后两个堆的变化,发现0x012800000该地址的堆增加的很快而其他堆没什么变化

下面进一步定位

命令:!heap –stat –h 查看对应对的状态,发下该堆的内存基本被长度为0x424的块占用,接下来我们在堆中搜索该进程中哪些模块占用0x424长度内存,如下图

命令:!heap –flt s 424

通过搜索程序内存中的堆发现长度为424的堆被大量的占用,进一步查看时谁在使用这个地址

找到泄露点了,红色部分的,如果程序对应的符号对应我们可以查看内存泄露点在哪一行

内存泄露分析结束,如果你还有什么好的方法可以共享


展开阅读全文

没有更多推荐了,返回首页