一、mtrace原理
- 函数拦截机制:mtrace 利用 glibc 的内部机制,对 malloc() / calloc() / realloc() / free() 等内存函数进行 hook,记录每一次分配和释放行为。
- 日志记录:记录会写入 MALLOC_TRACE 环境变量指定的日志文件中,包含:
- 分配的地址
- 大小
- 操作类型(M: malloc, F: free)
- 调用栈返回地址(可用 addr2line 还原)
二、mtrace定位内存泄漏问题(以gtest测试框架为例)
1、main.cpp中添加mtrace
(gtest默认的main文件要删掉src_code/srcs/API_with_gtest.cpp)
#include <gtest/gtest.h>
#include <mcheck.h> // mtrace 所在头文件int main(int argc, char** argv)
{// 先设置环境变量(可选)设置生成的log地址setenv("MALLOC_TRACE", "./gtest_mtrace.log", 1);// 启动内存追踪mtrace();::testing::InitGoogleTest(&argc, argv);return RUN_ALL_TESTS();muntrace(); // 关闭追踪,写日志
}
2、cmake里面添加add_executable(*** main.cpp),编译
注意编译debug版本 set(CMAKE_CXX_FLAGS_DEBUG "-g -O0")
检查mtrace有没有被编进程序 :
nm ./Api_Test_Tool_ARC_AVM_AutoCalibrate__imageInfo__010 | grep mtrace
3、chmod 777 执行程序的目录
chmod 777 /tmp/apitest 保证目录可以被写入
4、执行程序,生成./gtest_mtrace.log
5、用 mtrace 工具分析日志
在 PC 上执行:
mtrace ./Api_Test_Tool ./gtest_mtrace.log
输出:没有free的内存
Memory not freed:
-----------------
Address Size Caller
0x0000000001da5090 0x30 at 0x73fa515c
0x0000000001da5428 0x18 at 0x73fa515c
0x0000000001da5ae0 0x88 at 0x73fa515c
6、用addr2line定位没有解析出来的地址
$ addr2line -e ./ATT/Api_Test_Tool_ARC_AVM_AutoCalibrate__imageInfo__010 0x73fa515c
输出:??:0
🧨 原因 1:地址不属于这个 ELF 的 .text 区段
我们来确认地址 0x73fa515c 是否属于这个 ELF 的 .text 段(即:代码段),如果不在范围内,那说明这个地址来自其他 .so,比如某个算法库。
✅ 检查 .text 段地址范围
执行
readelf -Wl ./ATT/Api_Test_Tool_ARC_AVM_AutoCalibrate__imageInfo__010 | grep LOAD
输出:
LOAD 0x000000 0x00010000 0x00010000 0x100eb8 0x100eb8 R E 0x10000
LOAD 0x101d90 0x00121d90 0x00121d90 0x008c8 0x00d1c RW 0x10000
程序的 .text 段(可执行代码段)在 虚拟地址范围是:
0x00010000 ~ 0x00010000 + 0x100eb8 ≈ 0x00110eb8
所以这些地址不在可执行程序内
用addressline定位动态库地址参考:Addr2line使用-CSDN博客