mtrace 是 GNU libc 提供的轻量级内存追踪工具,仅跟踪 malloc/free 等 C 风格堆操作,需在 main 中调用 mtrace()/muntrace()、编译加 -g、设置 MALLOC_TRACE 环境变量,日志记录分配/释放序列,mtrace 命令可定位未配对的泄漏点。

mtrace 是 GNU libc 提供的轻量级内存追踪工具,专为 C 程序设计,但也能用于 C++ 程序——前提是不依赖 new/delete 的底层封装(如 STL 容器内部调用 malloc/free 时仍可捕获),且需手动开启追踪钩子。它不分析对象生命周期或 RAII 行为,只跟踪 malloc、realloc、memalign、free 这类 C 风格堆操作的实际调用路径与匹配关系。
必须修改源码并显式启用追踪
mtrace 不是 LD_PRELOAD 类工具,无法无侵入运行。你得在 C++ 主程序入口附近插入钩子控制逻辑:
- 包含头文件:
#include <mcheck.h></mcheck.h>(注意:不是或 ) - 在
main()开头调用mtrace(),在退出前调用muntrace() - 若使用多线程,确保仅主线程调用这两个函数(mtrace 非线程安全)
- 避免在构造函数、全局对象初始化中调用 mtrace —— 此时 malloc 钩子可能尚未就绪
编译和运行时的关键约束
生成有效日志依赖两个硬性条件:
- 必须加 -g 编译选项:否则 mtrace 分析时无法将调用地址映射回源码行号
-
必须设置 MALLOC_TRACE 环境变量,指向可写路径,例如:
export MALLOC_TRACE=./mtrace.log
也可在代码中用setenv("MALLOC_TRACE", "mtrace.log", 1)替代,但需早于 mtrace() 调用 - 链接时无需额外库;但若程序用了静态链接 libc(-static),需确认 glibc 版本支持 mcheck(主流发行版均支持)
日志内容反映的是真实分配/释放序列
运行后生成的日志不是堆快照,而是按时间顺序记录的每一次 malloc/free 操作,格式如:
立即学习“C++免费学习笔记(深入)”;
= Start @ ./a.out:[0x401156] + 0x1e2a010 0x64 @ ./a.out:[0x401168] - 0x1e2a010 @ ./a.out:[0x40117a] + 0x1e2a090 0x12c @ ./a.out:[0x40118c] = End
其中:
「+」表示 malloc(含地址、大小、调用位置)
「-」表示 free(含地址、调用位置)
未配对的「+」即为泄漏点,mtrace 命令会直接标出其源码行
用 mtrace 命令定位泄漏源头
执行:mtrace ./a.out mtrace.log,输出类似:
Memory not freed: ----------------- Address Size Caller 0x1e2a090 0x12c ./a.out:14
这表示第 14 行的 malloc 分配了 300 字节(0x12c)但未 free。注意:
• Caller 显示的是二进制中该 malloc 指令所在行,不是 new 表达式所在行
• 若该行是 std::vector::push_back 内部调用,说明泄漏来自容器扩容,需回溯上层逻辑
• 若程序中途崩溃,日志可能不完整,建议在关键路径前后加 printf 辅助判断执行范围


















