在Blade中结合gperftools检查内存泄露

Blade是我们开发的大规模C++项目构建工具。

gperftools是google开发的性能工具,由高效内存分配器,CPU性能分析器,堆分析器,堆检查器等工具组成。

和其他构建工具不同,结合gtest,Blade直接集成了对测试的支持,使得你可以像构建代码一样运行测试。

为了进一步提高测试的效果,我们还在测试中集成了gperftools的heapchecker,能够发现如下问题:

  • new和delete不匹配,比如new[]分配的用delete而不是delete[]释放。或者用free释放。
  • 堆内存写越界。
  • 内存泄露。

今天我们主要讲如何用blade测试来发现和分析内存泄露。

首先我们得写一个cc_test类型的blade构建目标。

然后我们运行这个测试:

blade test :xxx_test

不管测试成功失败,程序正常结束后(也就是没崩溃),如果有内存泄露,会出现这样的画面:

第一个红框内报告了泄露的位置,看不懂?我也看不懂,不过第二个红框内给了我们解谜的咒语:

我们把它拷下来,把结尾的--gv替换成--dot,然后执行,得到如下结果:

依然看不懂?下面这块是dot语言描述的图,我们可以用graphviz工具把它转为图形。把结尾换成--pdf就得到pdf,换成--svg就得到svg,都是矢量图,很方便查看。

可以用sudo yum install graphviz来安装,在我用的老旧的开发机上,因为缺乏包管理,安装比较麻烦,依赖一大堆东西。但是我通过搜索发现可以通过的这个网站在线把它转为图形:

把那段dot代码拷贝到左侧编辑区,稍等片刻,右侧就会出现图,如果不够大还可以另开个tab单独打开,就能很容易地看到内存泄露的代码位置和上下文了。如果dot太长可以先重定向到文件。

在Blade默认配置中,测试的HeapCheck功能没有开启,你可以在你的BLADE_ROOT文件中全局开启

其中的heap_check值请参考这里,一般设置成normal或者strict即可。

如果你的项目全局没开启,或者因为比如你的某个测试因为比如用了没有源代码但又不得不用的劣质某个第三方库等诸多原因问题而无法通过,可以在cc_test中单独设置这个属性,只对这个测试生效。设置为空字符串表示禁用。

通过这样的方式,内存泄露会导致测试失败,从而进一步保证了代码质量,只要有基本的单元测试,绝大多数内存泄漏都能在测试阶段发现。

不过,要消除内存泄漏,从代码风格上做更容易,比如用智能指针保存局部对象或者聚合的子对象,用string取代C字符串,用vector代替new数组,在现代风格的C++代码中,应该很少见到裸露的delete语句才对,这才是更基本的解决办法。

posted on 2014-11-04 22:22  chen3feng  阅读(2143)  评论(4编辑  收藏  举报

导航