【厚积薄发系列】C++项目总结7—实际项目中内存泄漏问题排查及常见情况总结

需求背景:

C/C++项目中,有时候最头痛不是业务需求实现问题而是随着项目的日益庞大过程中内存泄漏带来的问题。内存泄漏不仅会导致程序内存不够导致程序崩溃,还会导致内存碎片,更严重还会引起系统莫名其妙的崩溃和闪退。所以在项目中解决内存泄漏问题势在必行。

解决思路:

分两种情况

第一种情况项目是新启动的代码量也很少,这时候可以从源头来避免内存泄漏问题,可以考虑引入智能指针自动化管理内存释放问题,也可以引入Tcmalloc内存分配工具减少内存碎片问题。(第一种后续文章详说)

第二种情况项目已经开放一段时间了,已经进入中后期。此时的项目可能由于前期为了早点上线加班加点的实现新功能,会留下很多技术债,C/C++项目中比较头痛的就是内存泄漏问题。

系统内存布局分为堆区、栈区、全局数据库、常量区、代码区。工作中常常说的内存泄漏问题就是指的堆区的内存泄漏,是指程序员自己通过malloc、new申请后没有调用free、delete导致泄漏的内存。

具体实现:

1、VLD内存泄漏分析工具引入(可以到网上下载),我这边有做成安装包形式的直接跟VS挂钩,安装后在vs直接包含头文件就可以用(针对所有vs项目),有需要的可以留言。

a、VLD工具包含三个部分include目录下有vld.h、vld_def.h;lib目录下有vld.lib,exe对应的bin目录下有vld_x8.dll和dbghelp.dll(这是32位的也有对应一套64位版本的)可以手动在特定项目目录中配置,就像使用第三方库那样配置使用即可。

b、在需要检查内存泄漏的模块函数入口文件包含vld.h头文件即可。

c、配置如果测试代码和结果如下







常见内存泄漏问题及避免方法总结:

1、malloc和free,new和delete没有配对使用。常见情况调用的函数申请内存返回出去后,外部需要注意内存的释放。

2、释放对象数组时,没有加[]。

3、缺少拷贝构造函数,可能会导致堆区的崩溃和内存泄漏。如果一个类里面有指针成员变量时,需要显示的写拷贝构造函数和重载赋值运算符。如果一个C++类没有定义拷贝构造函数,难么编译器会调用默认的拷贝构造函数来复制数据成员,如果类中右动态分配的内存空间的指针时,会导致两个对象指向统一内存空间,最后调用析构函数的时候会导致两次释放问题从而导致崩溃。同理两个对象都有动态分配的内存空间时候如果用=赋值的时候,会导致另一个对象指向的内存空间泄漏。

4、没有将基类的析构函数定义为虚函数。如果类成员变量中涉及到动态申请内存,且存在派生关系则需要将基类析构函数定义为虚函数。

5、指针容器,如std::vector<CTest*>,在clear容器或者删除元素的时候需要手动释放器元素内存。

6、指针赋值导致内存泄漏,如果原指针有值的话需要先把原有的内存释放。

7、扫尾函数的调用,如一些公共模块第三方库初始化和关闭相关接口的配对使用。

8、异常分支或者break、return语句导致的内存泄漏问题,正常流程有内存释放,如果有异常是否做到了内存释放。

9、单例模式生命周期问题。

10、线程的安全退出,防止线程异常中断导致的内存泄漏问题。

猜你喜欢

转载自blog.csdn.net/lujiang0120/article/details/80424690
今日推荐