预防内存泄漏规律总结

(一)如何预防

1. 早发现,早解决
每写完一个功能的代码,可以是函数、或者类、或者模块都应该进行测试。

如果公司有单元测试工具,那自然最好。如果没有可以自己写些测试函数。

这个除了对内存,对一般功能测试、函数接口测试等都是应该的。

程序的可调试性也是考虑一个程序员的功底,个人认为。

2. 有良好的设计
设计是个很大的话题,这里专门是针对内存的建议。

*2.1 养成良好的编码习惯*
	创建和释放要集中,在一个类中要配对,如 Init---UnInit,Create---Destroy。
	释放的顺序应和分配的顺序相反。这个说起来容易,做起来难。

*2.2 集中管理*
	例如使用内存池。内存使用对象比较多,或者使用频繁,例如像我们对文件的读写循环一般就需要使用内存池。

	如果只是小量使用,可能就是对象的初始化,或者定义一些文件名,一般用不上内存池,那么也应该集中放在一个函数中,例如上面提到的配对函数。

	原则不能太分散了,见过有些不规范的编程,可以叫做“随用随调(内存分配)”,这种情况看代码费劲,往往很容易出各种内存问题。

*2.3 用try catch,捕获异常*
	对所有的new/malloc、delete/free等相关的函数都应该加上,这在一些检查工具例如pc-lint有要求的。

	这里往往也能捕获到一些内存越界,踩坑经验总结(一)的案例二。

*2.4 对内存的变化加日志跟踪*
	特别是异常情况,例如判断输入的缓冲长度和输出长度。

*2.5 DLL动态库的特别之处*
	我们以提问的方式来说明,一些注意事项。

	(1)DDL的库内部分配的内存,是否可以在调用者模块中释放? 即 A库分配的内存可以在B库释放吗?
	(2)如果不释放,除了内存泄露外,有没有其他影响?

	 答:(1)模块间内存使用一黄金原则:谁分配谁释放。
	(2)当系统退出时,该DLL需要5秒的时间来清理资源。也就是说比正常退出延时5秒。

(二)如何解决

上面的方法适用于开发阶段。而真正到了维护阶段,重点不一样了。

1. 了解程序的流程和设计原理

	你要解决一个问题,首先要了解它的来龙去脉。
	
	*1.1 主体流程*
		首先要对程序要有个大体认识,理解业务大体流程和模块之间的关系。
		尽量拿到框架设计图和类图,如果没有简单画一画。

	*1.2 关键细节*
		数据的流向往往都需要通过缓存作为载体,所以抓住关键的对象,这些对象一般使用频率较高,注意内存指针的移动,可以画画时序图。

	*1.3 尽量重现,找到规律*
		找到规律了,我认为就成功一半了。找到规律可以缩小范围,可以定位到某个功能点或者某个模块,要是某个类就更好了。

	*1.4 开源库的排查*
		主要排查启动和退出的时候内存的使用。

		我一直认为开源库的稳定性一般没有太大问题,因为有很多高手在维护。问题是我们在使用的时候,有时没有理解他的流程和原理,所以由回到了上面。这里举两个小例子说明。

		SIP协议库,还在上一家公司好像是VOIP的一个项目,出现了内存泄露,后面排查是会话的退出有个释放函数没有被调用。当时经验不足,用了C语言的检测工具,调试时间还是比较久的。 

		SNMP开源库,是在这家公司做一个批量升级工具,出现了内存泄露,当时直接查了下退出的一些函数,一个个释放函数试试,调试几番就解决了。

		开源库一般会比较复杂点,我记得这两个库的释放函数都不简单,又都是C语言写的,指针飞来飞去的,会把你给看晕,文档可能不是你想要的,最重要的是你可能只是使用下,没想过要深入。但是同样解决起来也是相对比较容易的。 

2.工具
两种工具,一种是自研的,可以跨平台。一种是windbg的umdb。

(三)难点

最后,复杂问题的内存泄露的难点是什么?

是编写一个检测工具,还是工具的熟练使用?我的回答都不是,工具固然重要。但是有了工具,如何使用,真的都能查得出来?

例如我们的案例里面,是和三、四个模块,好像都有关。所以虽然自研的工具应该更好用,但是不可能每个模块的每个类都去改下宏,工作量极大。但是后面用umdb也没有找到原因。当然正规的查找也还是需要,事实上umdb还是提供了很好的线索。

但是最后谁也没想到是一个不该使用而使用了的配置项!但是为什么还是发现了,有个很重要的观点,全局观!

再例如我们上面说的DLL库、开源库等等,用普通的思维(定势思维)可能很难理解,但是你站在更高一点,你从外面全局审视一下,你发现就可以理解了。

在庞大的程序中,程序结构或者系统分析才是重点和难点。当系统较复杂时候,是否需要全部检查还是检查某个模块;以及在哪个时候哪个地方进行释放。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值