检测和避免内存泄漏
在C++编程过程中,内存泄漏是一件令人痛苦的事情。当我们辛辛苦苦铺设好了完整的业务逻辑,把大段的代码实现填充完毕,开始Debug验证我们的成果的时候,也许开始的时候我们还在为得到了期望中的正确结果而高兴,但是,当程序结束时,当我们在Output窗口结尾处看到一行不起眼的“Detected memory leaks!”的时候,就会相当的不爽。因为,这就意味着:在程序的某些地方,有一些内存空间被分配了,但始终忘记了回收。
如果是那些比较简单,不会连续、重复执行的代码段,这种小的泄漏内存块并不会引起什么大的麻烦,最多就是运行的时候多占了一些内存罢了。但是话说回来,一般正常的程序员都会保证每个new、malloc的资源都会被delete、free掉,所以简单的程序里一般也不存在泄漏的问题。但凡出现泄漏,都是那种逻辑复杂、分支众多甚至还有不少try{…}catch{…}的代码段,最麻烦的是这些代码往往都是要进行连续重复调用执行的。这个时候如果出现了内存泄漏,那么我们就会发现,程序在运行的时候所占用的内存会一直增长,一直到Out of Memory或者死机;即使侥幸跑完整个逻辑,程序在Debug结束的时候,会在“Detected memory leaks!”后面输出泄漏内存块的信息,我曾经遇到过输出了10多分钟还没有结束的情况,最后只能开任务管理器把ide关掉。。。
有关内存泄漏检测与调试的文章,可以参考MSDN中内存泄漏检测和隔离一章节,以及Real-Time Library Reference中的_CrtDumpMemoryLeaks介绍(英文)。这里只是记录一些如何避免内存泄漏的个人意见:
- 保证每一个资源在你的代码范围内有始有终。对于每一个在你的代码控制范围内new、malloc的资源,尽量保证在离开你的代码控制范围之前delete、free掉;如果需要把资源传递给调用者,则需要和调用者约定最后的处理方法,是由调用者释放还是由调用者返回给你处理;如果你的代码也作为调用者获得了其他资源,则也同样要根据你和被调用者之间的约定来处理它们。
- 尽量把资源的申请/释放集中在一起,这样做不容易丢东西;也有不少资源可能是程序逻辑进行到某一步临时使用的,对于这些资源,可以使用之前申请,使用完成后立即释放,最好是2句语句可以在同一屏的代码窗口中看到。
- 确保无论程序执行哪一条逻辑通路,申请、释放资源的代码都会被执行到。有时候可能if{…}else{…}的逻辑一多,我们就不得不在每一个逻辑分支上加一些相同或类似的代码来处理一些事情(不限于内存申请/释放)。其实对于这种情况,我个人觉得首先需要重新考虑的,应该是程序逻辑,应该是可以重新设计重构复用掉那些相似的部分的。当然,不论怎样,必须要保证资源的申请/释放覆盖了每一条逻辑分支。这一点可以在测试时照顾到。
- 留意try{…}catch{…}和其他可能出现问题的地方。try{…}catch{…}往往是为了当错误发生时程序不至于崩溃掉,仍然可以继续运行而写的。当我们catch住了错误的时候,就要处理错误了,特别要注意的是,由于try中在出现异常的语句后面的代码不会被执行,所以这里的catch要对那一部分的逻辑进行“善后”,要注意处理和资源申请/释放相关的内容。
- 也可以尝试使用STL中的std::auto_ptr(非容器,数组等,可Google相关资料)或Boost C++ Libraries中的boost::shared_ptr系列。
浙公网安备 33010602011771号