welkinzz

服务器程序内存泄露问题跟踪

原文地址:http://hi.baidu.com/algorithms/blog/item/cc8c8c1bfffd69148718bf3d.html

 

写服务器程序,最怕的就是内存泄露。因为程序经常运行好几个月不停,一点点内存泄露都会导致悲剧的发生。常规来说,首要是避免内存泄露,其次是检查内存泄露。


避免内存泄露
1、不用new
c++程序,尽量多用stl,避免用new。我自己写的代码,除了在main函数里面有new外,其他地方不会再有任何new出现。这样就把内存管理交给stl去做。
或许你会说,不用new怎么可能啊?
很简单,char数组用std::string代替,其他对象直接拷贝。除非你的对象很大很大,否则,一点点拷贝耗时,完全可以忽略不计。


检查内存泄露
2、每个重要结构都提供Info函数
给你的每个重要结构都加上一个Info函数,info函数返回一个string,描述当前结构的状态,如map的大小,内存占用的大小。在最顶层,不定时的输出(或者根据命令输出)各个对象的info结果。这样可以避免隐形的内存泄露,即不是内存泄露,但某个对象保持的大量对象的引用,导致对象无法被删除;


俺采用这种方式,发现过好几次隐形内存泄露的问题,即某个对象内部的map,不断的添加数据,也在不断的删除数据,但在某些特殊情况下,它不会删除。



3、stl内存泄露的问题
stl几乎没有内存泄露,但它有一个内存cache,这个cache对小对象的分配很友好。stl的一个麻烦是,它几乎不会释放这些空间,这样的一个结果是,你看到自己的程序内存占用不断的上涨。其实,理论上是不用害怕的,因为它涨到一定范围(如,机器只有几百兆可用空间了),就不会涨了。我的一个程序,启动时占用了12G,结果慢悠悠的涨到14.5G才停止增长(机器共16G),运行了5个多月,还是那么大内存。
如果你看它不爽,可以通过在运行程序前,export
GLIBCXX_FORCE_NEW=1,来让stl不要进行cache。注意,这个仅仅在gcc(g++) 3.3以后有效。



4、valgrind等内存检测工具
这个没有啥好说滴,直接下载,编译(注意,必须在configure的当前目录下执行configure,不能另外选一个目录),安装。执行:valgrind
--num-callers=20 --leak-check=full --leak-resolution=high --show-reachable=yes
--log-file=val.log xxx &,等过了几天后,把它kill。然后慢慢的看val.log文件吧。


当你采用了前面3个策略后,valgrind几乎没有啥效果,反正我从来没有从它这里获得任何有用的信息过。主要是因为前面几步保证了没有显式的内存泄露,所以,valgrind也就找不出来啥内存泄露了。



5、valgrind的工具massif
massif比valgrind好的地方在于,它会告诉你当前内存的分布情况。你可以看到占用了几百兆的程序到底是那些地方占用了内存。执行:valgrind
--tool=massif xxx。一般通过这个都可以看到明显的内存泄露。

posted on 2012-01-19 05:25  照世明灯  阅读(2367)  评论(1编辑  收藏  举报

导航