最直接的方法是用 --log-file 指定日志路径,如 valgrind --leak-check=full --log-file=valgrind-out.txt ./myapp,它将全部输出写入指定文本文件,支持相对/绝对路径,但不自动创建父目录,且需配合 --leak-check=full 才能显示详细泄漏信息。

用 --log-file 指定日志路径最直接
Valgrind 默认把报告输出到终端(stderr),但终端刷屏快、难保存、不方便后续 grep 或分享。最稳妥的做法是用 --log-file 显式指定文件名,比如:
valgrind --leak-check=full --log-file=valgrind-out.txt ./myapp
运行后所有输出(包括错误详情、泄漏摘要、调用栈)都会写入 valgrind-out.txt。注意:--log-file 生成的是普通文本,不是 JSON 或 XML —— 如果需要结构化数据,得额外加 --xml=yes(仅 Memcheck 支持)。
-
--log-file的路径支持相对和绝对路径;若目录不存在,Valgrind 不会自动创建,会报错退出 - 如果程序多次运行,建议在文件名里加入
%p占位符,例如--log-file=valgrind-%p.log,Valgrind 会自动替换成进程 PID,避免覆盖 - 不推荐只用
2>out.log重定向,因为 Valgrind 内部可能分多路输出(如调试信息走stdout、错误走stderr),重定向容易漏掉关键内容
--log-file-exactly 和 --log-file-qualifier 的适用场景
绝大多数情况 --log-file 就够用了。但如果你遇到下面两种需求,才需要考虑另外两个参数:
- 要严格按字面名写入(不插入 PID、不扩展环境变量),就用
--log-file-exactly=report.log—— 它绕过 Valgrind 的自动命名逻辑,适合 CI 脚本中固定产物名 - 想让日志名带时间戳或主机名,可以用
--log-file-qualifier=HOSTNAME配合环境变量,比如先export HOSTNAME=myserver,再运行 Valgrind,它会生成report-myserver.log类似效果(前提是启动前已设置好该变量)
这两个参数极少被需要,新手别提前纠结,先确保 --log-file 能正常写入再说。
日志里看不到 “definitely lost”?检查 --leak-check 是否生效
很多人以为只要加了 --log-file 就能捕获全部泄漏信息,结果打开日志发现只有几行初始化提示,没有泄漏摘要。根本原因是:泄漏检测本身是独立开关,必须显式开启。
-
--leak-check=no(默认值):完全不检查泄漏,日志里自然没相关内容 -
--leak-check=summary:只显示总数,不列具体块 -
--leak-check=full或--leak-check=yes:才会展开每个泄漏块的地址、大小、分配点调用栈 —— 这才是调试需要的粒度
所以完整命令至少得是:valgrind --leak-check=full --log-file=out.log ./myapp。漏掉 --leak-check=full,日志再全也没用。
日志文件为空或权限拒绝?优先查这三件事
运行完发现目标文件是空的,或者报 Can't open log file,通常不是 Valgrind 问题,而是环境干扰:
- 当前用户对目标目录没有写权限(尤其常见于
/var/log或 root-owned 路径) - 路径中包含未创建的父目录,比如指定
--log-file=logs/valgrind.log,但logs/目录根本不存在 - 程序本身崩溃得太早(比如段错误发生在 main 之前),Valgrind 来不及写日志就退出了 —— 此时可加
--quiet减少干扰输出,或改用--log-file-exactly排除自动命名逻辑影响
真正容易被忽略的是:Valgrind 日志写入是程序退出时一次性 flush 的。如果程序卡死、被 kill -9 终止,或因信号异常退出,日志可能不完整甚至为空 —— 这时候得配合 --time-stamp=yes 看最后一条有效输出的时间,辅助判断是否写入中途被中断。


















