记一次c++内存泄漏查找过程

断了今生、忘了曾经 提交于 2019-12-17 22:18:34

        上周从周五开始疯狂修仙,累的一批。

        周日正美滋滋的睡着回笼觉,准备补回觉,突然被一个电话打过来去公司查软件内存泄漏问题(连续查了两天)。

        当时软件的情况是24 小时内存增加600mb内存,而验收标准是连续跑24 * 7小时,所以对于32位程序来说将达到4.2GB

会出现内存无法分配的情况(超出32位指针访问地址的上限)。

        分析问题使用的方法有两种:

一、第一阶段

       目测法:

       通过注释部分模块,加速运行的方法,查看任务管理器,有无内存泄漏。

       时间:1天

       结果:不能查找出,感觉很多模块都没有泄露,又都有略微增长。

二、第二阶段

        时间:1天

        工具法:使用内存泄漏检测工具

        使用了的工具有:VLD(Visual Leak Detector),tMemoryMonitor,WinDbg

        其中WinDbg是在运行中抓取前后两次内存数据,然后对内存数据进行对比的方式,对抓取的时间节点很考究。

        VLD和tMemoryMonitor都是运行结束后再进行生成泄漏报告的方式

        VLD需要修改源代码,增加头文件(可以支持Debug版和Release版),会大大降低程序运行的速度。

        tMemoryMonitor只支持Release版,且对性能影响较小

三、工具使用方法

     1、tMemoryMonitor使用最简单,下载地址: http://wetest.qq.com/cloud/index.php/index/TMM

          (1)启动TMM

          (2)添加目标程序

          (3)启动目标程序并退出

          (4)页面查看结果

     2、VLD(支持VS 2008-2015)下载地址:https://kinddragon.github.io/vld/

         安装后

        通常在main函数所在的CPP文件中(任意CPP也可以)include<vld.h>即可

        运行程序,退出后产生检测报告

      注意事项:

    (1)如果有include"stdafx.h",则include <vld.h>放在其后,否则放在最前面

    (2)如果想将产生的日志保存到文件中,需要将vld.ini(VLD安装目录下)复制到可执行文件目录下,
       ReportFile =.\memory_leak_report.txt 
       ReportTo = both

    (3) 为了减少日志数量将重复泄漏选项日志合并,该默认值false为ture

    (4)默认情况下只会检测主程序的模块,要想增加其他模块的内存泄露检测,需要配置vld.ini文件中的ForceIncludeModules,多个模块用";"分隔,如:
    ForceIncludeModules = test.dll;test2.dll

  (5)如果需要在release下进行检查,需要把Debug版中VS工程的配置复制到Release版中(include目录和链接库目录以及链接库名称VLD.lib),同时在main函数中增加如下代码:

#define VLD_FORCE_ENABLE // 增加该宏定义
int main()
{
    VLDGlobalEnable();
    VLDReportLeaks();
    //user code start...
    //......
    //user code end
    VLDGlobalDisable();
}

四、结果

     通过上述各种手段和方式查询

     发现内存泄漏的原因如下:

#include <list>
struct Vecotr
{
	Vecotr()
	{
		e = new double[3];
	}

	~Vecotr()
	{
		delete [] e;
	}
	double* e;
};

void Test()
{
	std::list<void *> list_;
	for (int i = 0; i < 10; i++)
	{
		list_.push_back(new Vecotr());
	}

	for (auto iter : list_)
	{
		delete iter;
	}
	list_.clear();
}

  类似上述代码,定义了一个void *的指针容器,加入了一些数据Vecotor指针

  当delete void *指针时,不会执行Vecotor的析构函数

  从而造成内存泄漏
 

       

        

        

        

        

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!