文章目录

  • 前言
  • 一、工具编译
  • 二、排查步骤
  • 三、示例

前言

本文主要讲述linux下使用tcmalloc检查代码中内存泄露问题


一、工具编译

tcmalloc是gperf开源代码的一个工具,常常用来检查内存泄漏问题。源码下载地址:

https://github.com/gperftools/gperftools/releases

这里以编译gperftools-2.9.0为例,交叉编译指令如下:

1./configure --prefix="$PWD/install" --host=arm-linux-xx --enable-frame-pointers(2)make(3)make install(4)在安装目录 install 的lib目录下,找到libtcmalloc.a,bin目录下找到可执行程序pprof(pprof最后在哪里执行,编译哪个工具链的版本)--host:编译工具链--prefix :安装目录

二、排查步骤

  • 交叉编译gperf生成对应平台的libtcmalloc.a库,及编译服务器下可运行的pprof可执行程序;
  • 增加编译选项CFLAGS += -fno-omit-frame-pointer (保留函数调用关系)、CFLAGS +=-g、链接静态库libtcmalloc.a;
  • 调试程序增加SIGUSR1信号接收函数,用于抓取内存快照;
  • 编译带有调试信息的调试程序;
  • 使用特殊指令启动可执行程序,
  • 每隔一定时间发送SIGUSR1到调试程序,/home/config/tc目录下会生成快照文件(需要多个);
  • 拷贝设备内所有动态库到nfs,用于步骤8比对文件差异时使用。
  • 使用pprof分析两个快照文件间的差异,通过输出的内容查看内存泄漏点。

三、示例

  1. 修改Makefile或修改编译指令,增加编译选项和链接tcmalloc库,$path为libtcmalloc.a库文件存放位置。
CFLAGS+= -fno-omit-frame-pointer -gLDFLAGS += -ltcmalloc -L./lib
  1. 拷贝交叉编译生成的 libtcmalloc.a 静态库到 ./lib 目录下

  2. 增加SIGUSR1信号处理函数,函数实际调用 HeapProfilerDump() 函数进行内存快照记录。

#include #include #include "heap-profiler.h"static void signalHandler(int type){HeapProfilerDump("Tcmalloc Dump!");}/*处理信号*/static void signalIgnored(void){signal(SIGUSR1, signalHandler);}/* 进程入口 main函数 */int main(int argc, char *argv[]){/* 信号捕获 */signalIgnored();while(1){pause();}}
  1. 编译代码生成可执行程序 test(使用步骤1增加的编译选项编译)
  2. 创建目录/tmp/tc,手动启动可执行程序,启动命令如下,其中/tmp/tc为内存快照存放目录,需要提前创建。
HEAPPROFILE=/tmp/tc/hprof./test &
  1. 每隔固定间隔(建议1分钟以上),发送SIGUSR1到test进程。该信号每发送一次,则会保存一次内存快照,保存快照的路径为步骤5中设置的路径,即/tmp/tc目录,快照文件名为hprof.xxxx.heap文件,xxxx为发送信号的次数。

发送信号指令:可用kill -SIGUSR1 $pid 代替

killall -SIGUSR1 test

快照文件生成:

7. 拷贝test可执行程序所依赖的所有动态库文件到编译服务器tcmalloc目录下(不涉及动态库可以不拷贝)
8. 编译服务器使用pprof比对两个快照之间的差异,即从hprof.xxxx.heap文件中选择两个版本进行比较,这里以hprof.0004.heap与hprof.0006.heap为例,/data1/user1/lib为动态库目录,test为带有debug信息的可执行程序,指令如下,其中生成的hicoremap0406.txt文件即为差异文件:

./pprof --lib_prefix=/data1/user1/lib test --base=./hprof.0004.heap ./hprof.0006.heap --inuse_space --drop_negative --lines --show_bytes --heapcheck --edgefraction=1e-10 --nodefraction=1e-10 --text > test0406.txt

9.打开test0406.txt文件,查看文件内容,如有内存泄露,会显示类似如下格式的内容信息,test_fun_a 为可能泄露内存资源的函数名,29为行号,1048576为内存大小。

Total: 6294476 B104857616.7% 100.0%104857616.7% test_fun_a 29:0328 0.0% 100.0%328 0.0% 0000000075ffa5d472 0.0% 100.0% 72 0.0% 0000000075fd4dec60 0.0% 100.0% 60 0.0% 0000000076005a5024 0.0% 100.0% 24 0.0% 0000000075ff6c58