linux 内存泄漏排查--多种工具介绍
目录
1.工具
2.valgrind
2.1.Valgrind 安装
2.2.valgrind 使用
2.3.valgrind常见的命令行选项如下:
2.4.日志分析
3.mtrace
3.1.使用
3.2.注意
3.3.结果分析
4.bcc工具里面的memleak-bpfcc
4.1.命令安装
4.2.源码安装
4.3.结果分析
4.4.辅助命令
5.Sanitizer(AddressSanitizer)
5.1.sanitizer标志
5.2.使用
5.2.1.gcc/g++使用sanitizer
5.2.2.CMakeLists使用sanitizer
5.3结果分析
参考链接
1.工具
网上一查,linux下面的内存泄漏工具很多,这里将主要介绍:valgrind,mtrace,bcc工具里面的memleak-bpfcc与Sanitizer(AddressSanitizer)
2.valgrind
2.1.Valgrind 安装
安装连接:Valgrind: Current Releases
自己选择自己需要的版本,
tar -jxvf 压缩包
cd 解压出来的路径
./configure
make
sudo make install
到这里安装完毕了,可以使用下面这个命令查看是否安装完毕
valgrind --version
2.2.valgrind 使用
下面这条命令是本人比较喜欢使用的,具体命令参数可以查看下面的说明。
valgrind -v --log-file=valgrind.log --tool=memcheck --leak-check=full --show-mismatched-frees=yes ./main # ./main是可执行文件的名字
2.3.valgrind常见的命令行选项如下:
--tool=<toolname>:指定Valgrind使用的工具,比如Memcheck、Cachegrind、Helgrind等;未指定则默认Memcheck;
--leak-check=<yes|no>:开启或关闭内存泄漏检测。如果指定为yes,则Valgrind会在程序结束时输出内存泄漏信息。
--show-reachable=<yes|no>:控制是否显示可达但未释放的内存块。如果指定为yes,则Valgrind会输出这些信息,但这些信息并不表示内存泄漏。
--track-origins=<yes|no>:开启或关闭变量值溯源。如果指定为yes,则Valgrind会跟踪变量的值的来源,可以帮助查找悬挂指针和野指针等问题。
--num-callers=<n>:指定调用栈的层数。如果指定为n,则Valgrind会输出n层的调用栈信息。
--log-file=<filename>:指定输出信息的文件名。如果未指定该选项,则Valgrind会将输出信息打印到标准输出。
--vgdb=<yes|no>:开启或关闭vgdb调试服务。如果指定为yes,则可以使用gdb等调试器来远程连接Valgrind并进行调试操作。
--trace-children=<yes|no>:是否跟踪通过exec产生的子进程,默认不跟踪,但是对于fork产生的子进程会跟踪;
--version:Valgrind的版本号;
2.4.日志分析
图片数据来源参考链接第一个链接
Memcheck将内存泄露分为两种,一种是可能的内存泄露(Possibly lost),另外一种是确定的内存泄露(Definitely lost)。Possibly lost 是指仍然存在某个指针能够访问某块内存,但该指针指向的已经不是该内存首地址。Definitely lost 是指已经不能够访问这块内存。而Definitely lost又分为两种:直接的(direct)和间接的(indirect)。直接和间接的区别就是,直接是没有任何指针指向该内存,间接是指指向该内存的指针都位于内存泄露处。在上述的例子中,根节点是directly lost,而其他节点是indirectly lost
3.mtrace
3.1.使用
#include <mcheck.h>
//"/zdrive/logs/MY_Trance.log" 为日志输出路径
setenv("MALLOC_TRACE", "/zdrive/logs/MY_Trance.log", 1);
mtrace();
//需要定位的地方
muntrace();
日志输出,可以在代码里面设置,也可以配置环境变量
导出内存记录文件路径的环境变量:$ export MALLOC_TRACE=
/zdrive/logs/MY_Trance.log
3.2.注意
编译:加上 -g
参数,在程序中记录调试信息。是为了后面进行程序地址转换为代码文件位置。
3.3.结果分析
数据集来自参考链接二
$ cat trace.log
= Start
@ ./a.out:[0x40062b] + 0xf15460 0x64
@ ./a.out:[0x40063b] - 0xf15460
@ ./a.out:[0x400645] + 0xf154d0 0x3e8
= End
+ 表示分配;- 表示释放
可以使用 mtrace
命令来分析记录文件。mtrace
命令是 glibc-utils
的工具,是一个 perl
脚本文件,通过调用 addr2line
命令来进行解析代码文件位置。如果无该命令,可以安装 glibc-utils
来安装该命令。
$ mtrace a.out trace.log
Memory not freed:
-----------------Address Size Caller
0x00000000013fc4d0 0x3e8 at /home/centos/gnuc/c3/mtrace.c:13
4.bcc工具里面的memleak-bpfcc
4.1.命令安装
安装bpftool
apt-get install -y linux-tools-$(uname -r)
bpftool version
sudo apt-get install bpfcc-tools linux-headers-$(uname -r)
sudo apt-get install -y bpftrace
4.2.源码安装
源码安装比较复杂,而且麻烦,但是可以突破一些公司环境限制问题。我个人比较推荐源码安装。
安装包数据的链接后面会贴,可以在下载链接里面下载,也可以找我要。
4.3.结果分析
在日志里面可以看到内存申请的地方,[里面会标使用的地方]
4.4.辅助命令
memleak-bpfcc会5秒刷新一次,可以在memleak的帮助手册里面进行查看,进行配置
5.Sanitizer(AddressSanitizer)
5.1.sanitizer标志
sanitizer已经被集成到gcc,在使用只需要设置相应的标志位即可:相应标志如下
地址错误: -fsanitize=address
内存错误: -fsanitize=memory
内存泄漏: -fsanitize=leak
线程竞速问题: -fsanitize=thread
未定义问题: -fsanitize=undefined
5.2.使用
5.2.1.gcc/g++使用sanitizer
gcc/g++编译只需要将sanitizer的标志作为flag设置即可,如下:
gcc/g++ -fsanitize=address -g -fno-omit-frame-pointer test.cpp
5.2.2.CMakeLists使用sanitizer
使用CMAKE_CXX_FLAGS或add_compile_options的配置即可使用,如下:
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer")
或add_compile_options(-fsanitize=address -fsanitize=memory -fno-omit-frame-pointer)
link_libraries(-fsanitize=address -fsanitize=memory)
5.3结果分析
数据来源于 链接三,主要错误结果在前面几行。
=================================================================
==79521==ERROR: AddressSanitizer: stack-buffer-overflow on address 0x7fff4c428dd8 at pc 0x563deecc541d bp 0x7fff4c428d90 sp 0x7fff4c428d80
READ of size 4 at 0x7fff4c428dd8 thread T0#0 0x563deecc541c in f() /home/zmy/test_cpp/sanitizers/address_sanitizers.cpp:6#1 0x563deecc54ae in main /home/zmy/test_cpp/sanitizers/address_sanitizers.cpp:12#2 0x7f813aa660b2 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x270b2)#3 0x563deecc522d in _start (/home/zmy/test_cpp/sanitizers/a.out+0x122d)Address 0x7fff4c428dd8 is located in stack of thread T0 at offset 40 in frame#0 0x563deecc52f8 in f() /home/zmy/test_cpp/sanitizers/address_sanitizers.cpp:4This frame has 1 object(s):[32, 40) 'a' (line 5) <== Memory access at offset 40 overflows this variable
HINT: this may be a false positive if your program uses some custom stack unwind mechanism, swapcontext or vfork(longjmp and C++ exceptions *are* supported)
SUMMARY: AddressSanitizer: stack-buffer-overflow /home/zmy/test_cpp/sanitizers/address_sanitizers.cpp:6 in f()
Shadow bytes around the buggy address:0x10006987d160: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d170: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d180: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d190: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d1a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
=>0x10006987d1b0: 00 00 00 00 00 00 f1 f1 f1 f1 00[f3]f3 f3 00 000x10006987d1c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d1d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d1e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d1f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 000x10006987d200: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Shadow byte legend (one shadow byte represents 8 application bytes):Addressable: 00Partially addressable: 01 02 03 04 05 06 07 Heap left redzone: faFreed heap region: fdStack left redzone: f1Stack mid redzone: f2Stack right redzone: f3Stack after return: f5Stack use after scope: f8Global redzone: f9Global init order: f6Poisoned by user: f7Container overflow: fcArray cookie: acIntra object redzone: bbASan internal: feLeft alloca redzone: caRight alloca redzone: cbShadow gap: cc
==79521==ABORTING
参考链接
(2条消息) Linux 下几款程序内存泄漏检查工具_ubuntu 内存泄露_youbingchen的博客-CSDN博客
mtrace-内存使用追踪(内存) - 简书 (jianshu.com)
(3条消息) c++使用sanitizer代码分析_明霁天明的博客-CSDN博客
(3条消息) ubuntu21.10搭建ebpf环境,BCC和bpftrace_bpftrace安装_伊库塔花花的博客-CSDN博客
(3条消息) ubuntu安装llvm教程_自有林中趣的博客-CSDN博客
使用 libbpf 开发 eBPF 程序 - Cheneytian's Blog (cheneytianx.github.io)