一、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博客