为何perf report显示Server::onRecvBlock调用__libc_start_call_main?
perf报告调用链异常问题排查
perf报告片段
Samples: 47K of event 'cycles', Event count (approx.): 22843195013 Children Self Command Shared Object Symbol + 97.13% 0.01% server server [.] Server::runEventLoopOnce ◆ - 96.70% 52.84% server server [.] Server::onRecvBlock ▒ + 46.21% 0x7fd3fa4f9253 ▒ + 43.86% ServerQueue::onRecvBlock ▒ + 6.61% __libc_start_call_main ▒
问题描述
我使用perf record --call-graph=fp ./server采集性能数据,可执行文件编译时已经添加了-fno-omit-frame-pointer参数,为什么perf report会显示我的函数Server::onRecvBlock()调用了__libc_start_call_main?
原因分析与解决建议
这种异常的调用链显示大概率是栈回溯出错导致的,常见诱因包括:
- 栈切换时的帧指针断裂:当进程触发系统调用或中断时,内核会切换栈空间,如果此时恰好发生perf采样,原本的用户态帧指针链会被打断,导致回溯逻辑错误地关联到进程启动入口的
__libc_start_call_main函数。 - 帧指针优化的漏网情况:即便添加了
-fno-omit-frame-pointer,部分编译器版本、内联函数场景或是动态链接库的调用,仍可能出现帧指针不连续的情况,破坏perf的回溯链路。 - 采样上下文异常:如果采样发生在进程初始化残留栈帧、线程创建/销毁的临界阶段,也可能出现这种错误的调用关联。
对应的解决方法:
- 改用
--call-graph=dwarf参数进行采样,dwarf通过调试信息实现栈回溯,精度比fp更高,能适配更多复杂场景。 - 确认使用的编译器版本(比如GCC 8及以上版本对
-fno-omit-frame-pointer的支持更稳定),避免旧版本的编译器bug。 - 检查依赖的动态链接库是否也添加了
-fno-omit-frame-pointer编译参数,如果第三方库未开启帧指针,同样会打断回溯链。
内容的提问来源于stack exchange,提问作者rafoo
相关产品推荐
相关产品推荐

