You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker中Perf报告C++程序共享对象显示为(deleted)的问题

Swift与C++程序Docker环境下Perf性能分析差异问题解答

问题背景

我在带--privileged参数的Swift Docker镜像中,对两个执行相同循环数学计算的二进制程序(分别用Swift和C编写)做性能分析。已知该Docker实例里的系统库libm.so和libc.so已被剥离,符号解析效果有限,但C程序的Perf报告中共享对象显示为(deleted),Swift程序则无此问题。

C++程序编译参数:

-g -O3 -Wall -Wextra -pedantic -std=c++20 -fwrapv -fno-omit-frame-pointer -mno-omit-leaf-frame-pointer

通过perf record -g记录数据,perf report -g 'graph,1.0,caller'的输出里有大量(deleted)条目(对应libm.so、libc.so和kernel.kallsyms),且调试时无法在报告中的地址设置断点(提示Cannot access memory at address 0xffff88fe54e4)。

Swift程序的Perf报告能正常显示共享对象名称及符号。另外调试发现,C++程序通过过程链接表(PLT)直接跳转至log函数,而Swift程序需通过dlsym查找。


1. 两份报告差异的可能原因

  • 库加载机制差异:C++程序通过PLT直接绑定系统库符号,依赖镜像中原始的libm.so/libc.so文件;但这些库已被剥离删除,Perf解析采样地址时找不到对应文件,只能标记为(deleted)。Swift程序用dlsym动态查找符号,加载的是镜像中当前存在的、可被Perf识别的库实例(可能Swift运行时自带了相关符号表或加载了未被完全剥离的库副本)。
  • 镜像库状态不同:Swift Docker镜像为兼容运行时,可能保留了部分系统库的符号信息或未完全剥离;而C++编译后直接依赖的是被彻底删除的系统库文件,Perf无法关联到有效文件路径。
  • Perf解析适配性差异:Swift程序的二进制或运行时包含额外调试/符号信息,让Perf能正确映射共享对象;C++程序的PLT跳转地址指向已删除的库文件,Perf无法通过当前系统库匹配对应地址,只能显示(deleted)。

2. 优化C++程序Perf报告效果的方法

  • 静态链接系统库:编译时添加-static参数,将libm/libc代码静态链接到二进制中,避免依赖已剥离的动态库。Perf采样时可直接解析二进制内的符号,无需外部库文件。
  • 导入符号文件:从同版本系统获取未被剥离的libm.so/libc.so符号文件,放到Docker镜像对应路径,或通过perf buildid-cache --add手动导入,让Perf关联采样地址与符号。
  • 增强编译符号信息:用-ggdb替代-g保留更完整的调试信息;确保-fno-omit-frame-pointer参数生效,帮助Perf更准确解析调用栈,减少无法识别的地址条目。
  • 手动添加探针:对无法解析的系统库函数(如log),使用perf probe在C++程序的PLT跳转位置手动添加探针,补充符号信息,让Perf报告显示对应函数名。
  • 恢复镜像库符号:若镜像支持包管理,安装libc6-dbg或libm-dev包,恢复系统库的符号信息,让Perf正常解析共享对象。

内容的提问来源于stack exchange,提问作者loonatick

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 06:07:47