Home > programming > 内存泄露 (续)

内存泄露 (续)

  在现场的一个服务有巨大的内存泄露的问题,最近一直都在检查这个问题。虽然看起来还有一点泄露,不过已经能够让现场可以撑得更久一点了。

  现场的一个播流的服务(实际上时一个速率可控的http下载的服务器端),由于前一段时间性能不能达到客户的要求,而大幅修改过很多的代码。而且又需要立马上线,结果不能很好的测试就把匆忙修改的程序部署到了现场。现在想起来真实悲催啊,因为性能问题而修改累了一段时间,现在有需要给这个没有充分测试的程序做扫尾动作。

  当现场报说有大量内存泄露以后,我就开始着手使用分析工具来看看泄露到底是什么地方引起的。 我选择了google performance tool来查看内存泄露的点. 安装google perf tool测试一段时候,根据google perftool的提示和code review找到了一些内存泄露的代码。但是奇怪的就是修复了这些泄露点以后重新build一个版本做压力测试发现还是有内存泄露。这个让我觉得很是奇怪,再次使用google perftool测试,但是该工具没有报告任何的内存泄漏点,这个让我一度怀疑这个工具是有问题的。不过后来一想,我们的应用用到了很多的stl class,特别是std::map std::list等东西, 如果这些实例析构以后所占用的内存会被释放,而google perftool是要在程序退出以后才能报告是否有内存泄露。如果一个程序在运行的过程中不断的向一个list或者map插入新的记录但是忘了删除的话,这个依然是一个内存泄漏点。为了验证我的想法,我在google perftool的代码加入了一个signal的响应函数,当接收到这个siganl的时候就做一次内存泄露报告。然后使用这个修改后的google perftool进行测试,程序在大压力的环境下跑了半个小时以后,把所有的测试客户端都停掉(防止在report memory leak的时候还有代码需要做内存分配/释放操作)。然后查看内存泄露报告,发现确实如我所想,内存泄露大都来之std::map中的record没有删除而造成的。

  当我以为这些内存泄露点都修复好了程序就应该没有什么问题了,接下来的压力测试让我觉得有点摸不着头脑了。程序在大压力的情况下跑了48+小时后发现有400M+的内存泄露,停掉所有的客户端以后内存使用并不会回到最初状态。而在此使用google perftool进行检测却找不到有内存泄漏点。迷惑了很长时间以后google了一番找到了http://www.nosqlnotes.net/archives/105这篇文章,也就是GLIBC的内存分配/释放的缺省行为可能造成内存不会被正常交还给kernel(当然我的程序是否是这个问题还需要进一步确认)。

  查找完内存泄露点以后觉得很有必要做一个记录,也好给自己做一个提醒。

1.  malloc / new 以后没有free/delete。

2.  加入到map list vector等容器中的record没有及时删除

3.  智能指针的循环引用,例如A和B是两个实力,其中A有一个智能指针指向B,而B也有一个智能指针指向A。如果不主动调用A或者B的资源释放方法的话A和B均不会被析构

4.  还有就是没有考虑到所有的资源释放情形,导致在特殊情况下资源释放的方法不能被调用到

     例如,在调用了epoll_ctl(…, EPOLL_CTL_ADD , …)以后没有检查返回值,在某个情况下这个函数可能会返回错误,这个时候就应该调用资源释放函数(这个socket已经不可用了)

5. 还有啥?想到了再补充一下…

Categories: programming Tags: ,
  1. No comments yet.
  1. No trackbacks yet.