callgrind默认在当前工作目录生成callgrind.out.进程id文件,加--separate-threads=yes则按线程生成子文件;可用--callgrind-out-file指定路径,文件权限为-rw-------,需确保后续分析工具可读。

Callgrind 输出文件默认生成在当前工作目录
执行 valgrind --tool=callgrind ./my_program 后,Callgrind 会在你运行命令时所在的**当前终端目录**下生成一个形如 callgrind.out.<pid></pid> 的文件(例如 callgrind.out.12345),而不是程序源码目录或安装目录。
这个行为不受程序路径影响,只取决于 shell 当前 pwd。如果你在 /tmp 下执行命令,文件就落在 /tmp/;如果在 ~/project 下执行,就落在该目录下。
- 不加任何参数时,只生成一个主文件,对应主线程(即使程序多线程)
- 加了
--separate-threads=yes,会额外生成callgrind.out.<pid>-01</pid>、callgrind.out.<pid>-02</pid>等子文件,每个线程一个 - 文件是二进制+文本混合格式,不能直接用
cat读,需用callgrind_annotate或kcachegrind解析
如何确认文件是否生成成功
最直接的方式是命令执行完后立刻 ls -l callgrind.out.*。如果没看到,常见原因有:
- 程序崩溃退出过早(比如 segfault),Callgrind 来不及写完就终止 → 先用
valgrind --tool=memcheck排查基础错误 - 磁盘空间不足或当前目录无写权限 → 检查
df -h .和touch test.txt - 误用了
--instr-atstart=no但没在代码里调用CALLGRIND_START_INSTRUMENTATION宏 → 文件为空或极小(几十字节) - 程序是 daemon,后台 fork 后退出了父进程 → Callgrind 跟的是父进程,实际工作线程在子进程里,此时必须加
--trace-children=yes
想指定输出路径?用 --callgrind-out-file
Callgrind 支持显式指定路径,避免依赖当前目录:
valgrind --tool=callgrind --callgrind-out-file=/tmp/myapp.prof ./my_program
这样无论你在哪执行命令,结果都固定落在 /tmp/myapp.prof。注意路径需有写权限,且文件名不要带空格或特殊字符。
- 支持 printf 风格占位符:
--callgrind-out-file=/tmp/prof.%p中的%p会被替换成进程 PID - 如果目标路径是目录(如
/tmp/prof/),需确保末尾有斜杠且目录存在,否则会报错“failed to open” - 不建议写到 NFS 或 FUSE 挂载点——Callgrind 写入频繁,可能因延迟导致文件损坏或分析中断
容易被忽略的细节:文件权限与后续工具兼容性
生成的 callgrind.out.* 文件默认权限是 -rw-------(仅属主可读写)。如果你之后想用 kcachegrind 在图形界面打开,而它运行在另一个用户上下文(如通过 ssh -X 或容器内),就会打不开。
更隐蔽的问题是:某些旧版 gprof2dot.py 会静默跳过无法 stat 的文件,不报错也不输出 dot,最终生成空 SVG —— 这时候得先 chmod 644 callgrind.out.* 再试。











