加 -g 参数才能看到完整函数调用栈,因其启用帧指针或 DWARF 回溯;不加则仅记录最底层函数。需配合编译选项 -g 和 -fno-omit-frame-pointer,并注意内联与符号缺失问题。

perf record 采集时为什么必须加 -g 参数才能看到函数调用栈
不加 -g,perf record 默认只记录采样点所在的最底层函数(比如 std::vector::push_back),看不到它被哪个业务函数调用。加了 -g 才会通过帧指针(frame pointer)或 DWARF 信息回溯调用链,生成类似 main → process_data → compute_hash 的完整路径。
实际操作中注意三点:
- 编译 C++ 程序时务必加
-g(保留调试符号),否则perf report显示的函数名可能是???或地址偏移 - 推荐同时加
-fno-omit-frame-pointer,尤其在-O2及以上优化等级下,GCC/Clang 默认会省略帧指针,导致-g无法正确展开栈 - 如果程序用了
libstdc++的内联函数(如std::string::size()),即使有帧指针也可能被内联掉——这时需配合-fno-inline临时编译,或接受部分叶子节点不可见
perf report 里看到大量 [unknown] 或 _dl_runtime_resolve_xxx 怎么办
这是符号未解析的典型表现,常见于动态链接库缺失调试信息或 perf 权限不足。不是程序写得有问题,而是分析环境没配好。
优先检查并执行以下操作:
- 确认目标进程所用的
libc、libstdc++.so等共享库已安装对应-debuginfo包(如 CentOS/RHEL 装glibc-debuginfo,Ubuntu/Debian 装libc6-dbg和libstdc++6-12-dbg) - 用
perf buildid-list -i perf.data查看是否记录了 build-id;若为空,说明采集时未获取到库的 build-id,可尝试加--buildid-all重采 - 避免用
sudo perf record但普通用户跑perf report——权限不一致会导致符号读取失败;统一用非 root 用户运行(需提前配置/proc/sys/kernel/perf_event_paranoid≤ 2)
如何过滤掉 STL 模板实例和系统调用干扰,聚焦业务函数
perf report 默认展开所有符号,C++ 模板实例(如 std::_Rb_tree_insert_and_rebalance)和系统调用(如 sys_read)常占前几行,掩盖真实热点。
高效聚焦业务代码的方法:
- 用
perf report --no-children关闭自底向上聚合,避免子函数耗时被父函数“吃掉” - 启动交互式界面后按
/键搜索关键词,比如输入/MyService::handle快速定位业务类方法 - 导出火焰图前先过滤:用
perf script | awk '$3 !~ /std::|libc|libpthread|_dl/ {print}' | flamegraph.pl > hot.svg,剔除常见干扰项 - 若使用
perf record -e cycles:u(仅用户态),可天然避开内核路径,减少系统调用噪声
perf script 输出的调用栈里出现 ??:? 或地址偏移怎么办
这表示 perf 找不到该地址对应的源码行号,通常因为二进制缺少调试信息或编译时未开启 -g。但别急着重编——先验证是否真缺符号:
- 运行
file ./your_program,确认输出含with debug_info;若无,重新编译加-g -fno-omit-frame-pointer - 对已部署的 release 版本,可用
objdump -S ./your_program | grep -A5 "some_func_name"看是否能反汇编出源码行——若能,说明符号存在但 perf 没加载成功 - 强制 perf 加载本地调试信息:
perf report --symfs ./debug-root/,其中./debug-root/usr/lib/debug/...是你手动放置的.debug文件树 - 注意 C++ 名称修饰(mangling):
perf report默认显示修饰名(如_Z10do_work_i),加--demangle可还原为do_work(int),方便识别
真正难处理的是生产环境无调试符号又无法重启服务的情况——这时只能靠 perf record -e instructions:u --call-graph dwarf 采集更细粒度指令流,再结合 addr2line 手动查地址,但准确率下降明显。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











