在《内存问题分析的利器——valgraind的memcheck》一文中,我们介绍了如何使用valgrind分析各种内存问题。valgrind是基于模拟器的技术实现,而本文介绍的gperftools则是通过在用户代码中嵌入检测代码实现的。(转载请指明出于breaksoftware的csdn博客)
先介绍下gperftools的编译安装。
首先下载安装编译依赖的一些工具
sudo apt install autoconf
sudo apt install libtool
sudo apt install libtool-bin
然后从git上获取libunwind,并编译安装
git clone https://github.com/libunwind/libunwind.git
cd libunwind
sh ./autogen.sh
./configure
make
sudo make install
现在可以编译安装gperftools了
git clone https://github.com/gperftools/gperftools.git
sh autogen.sh
./configure
make
sudo make install
最后,我们安装下结果可视化分析工具kcachegrind
sudo apt install kcachegrind
由于heap checker是内存泄漏检测工具,我们构造一段有问题的代码
#include
int main() {
const int array_count = 4;
int* p = new int[array_count];
return 0;
}
这段代码第5行在堆上申请了空间,但是没有释放。为了包含更多调试信息,我们使用-g方式编译该文件
g++ leak.cpp -ltcmalloc -g -o leak
注意此处我们链接了tcmalloc库,它是gperftools内存问题分析方案的基础。一般来说,比较推荐链接该库,它的效率比编译器自带的内存管理库要高。
gperftools运行方式比较独特,对于heap checker工具,我们需要这样调用
HEAPCHECK=normal /home/fangliang/gperftools_test/heap_checker/leak
HEAPCHECK除了nomal外,还可以选择strict或者draconian。最后一个参数就是我们程序的路径。其分析结果展现如下
WARNING: Perftools heap leak checker is active -- Performance may suffer
Have memory regions w/o callers: might report false leaks
Leak check _main_ detected leaks of 16 bytes in 1 objects
The 1 largest leaks:
Using local file /home/fangliang/gperftools_test/heap_checker/leak.
Leak of 16 bytes in 1 objects allocated from:
@ 55f9903b8723 main
@ 7fed6bbc9b97 __libc_start_main
@ 55f9903b862a _start
If the preceding stack traces are not enough to find the leaks, try running THIS shell command:
pprof /home/fangliang/gperftools_test/heap_checker/leak "/tmp/leak.3384._main_-end.heap" --inuse_objects --lines --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --gv
If you are still puzzled about why the leaks are there, try rerunning this program with HEAP_CHECK_TEST_POINTER_ALIGNMENT=1 and/or with HEAP_CHECK_MAX_POINTER_OFFSET=-1
If the leak report occurs in a small fraction of runs, try running with TCMALLOC_MAX_FREE_QUEUE_SIZE of few hundred MB or with TCMALLOC_RECLAIM_MEMORY=false
Exiting with error code (instead of crashing) because of whole-program memory leaks
第6行显示我们程序有1块16字节的空间泄漏。第7到第9行,展示了泄漏处的调用堆栈。但是这个信息展现方式并没有直接指出问题产生的行数。我们可以使用其提示的第14行指令,调用可视化工具
如此,我们便可以清晰的知道,leak.cpp第5行代码申请的空间存在内存泄漏。
如果我们项目中不可以链接tcmalloc,我们还可以使用如下方式调用heap checker,其结果和上面描述的一致
LD_PRELOAD="/usr/local/lib/libtcmalloc.so" HEAPCHECK=normal /home/fangliang/gperftools_test/heap_checker/leak