strip 主要删除 .symtab、.strtab 和 .debug_* 段,但保留 .dynsym;因此动态链接正常,但调试信息丢失导致 gdb 无法显示符号和调用栈。

strip 会删掉哪些符号?
它主要移除 .symtab(符号表)、.strtab(字符串表)、.debug_*(所有调试段),但保留 .dynsym(动态符号表)——所以动态链接还能正常工作。
常见错误现象:用 gdb 加载 stripped 文件后显示 No symbol table is loaded,或者 bt 只能看到地址,看不到函数名和行号。
- 如果你没加
-g编译,本来就没调试信息,strip影响不大 - 加了
-g但没用-g3,strip会清掉所有line number和variable info -
strip --strip-unneeded比裸strip更激进,还会删掉未被引用的本地符号(比如未导出的static函数)
什么时候不该 strip?
不是所有可执行文件都适合 strip。核心判断点是:你是否需要在运行时或事后做符号级分析。
使用场景举例:
- 用
perf record -g采样后想看函数火焰图 → 必须保留.symtab或至少.dynsym,否则perf report显示全是[unknown] - 线上 crash 生成
core dump,用gdb ./a.out core调试 → 如果二进制被 strip 过,就无法还原调用栈和变量值 - 用
addr2line -e ./a.out 0x401234查地址对应源码行 → 依赖.debug_line段,strip 后直接失效
如何保留调试信息又减小体积?
直接 strip 掉全部调试段最省空间,但代价太高;更实用的做法是分离调试信息。
推荐流程(GCC/Clang 环境):
- 编译时加
-g,确保生成完整调试段 - 用
objcopy --only-keep-debug ./a.out ./a.out.debug抽出调试信息到独立文件 - 再用
objcopy --strip-debug ./a.out移除原文件中的调试段(保留符号表) - 最后用
objcopy --add-gnu-debuglink=./a.out.debug ./a.out建立关联
这样生产环境部署的是轻量版 a.out,但调试时 gdb 能自动找到同目录下的 a.out.debug,效果几乎等价于未 strip。
strip 后还能恢复符号吗?
不能。strip 是不可逆操作,删掉的 .symtab 和 .debug_* 段不会以任何形式残留。
容易踩的坑:
- CI/CD 流水线里对 release 包无条件 run
strip,结果 QA 环境遇到 crash 却没法定位 → 应该只 strip 部署包,保留带符号的 build artifact 存档 - 误以为
strip -S(删掉.stab)能“安全瘦身”,其实现代 GCC 默认不用.stab,这个参数基本无效 - 在容器镜像里
strip /usr/bin/myapp,却忘了该镜像还可能被用来 debug → 容器应分 base/debug/release 多阶段构建
真正关键的不是 strip 不 strip,而是符号和调试信息有没有被可靠存档、能否按需关联。线上二进制越干净越好,但对应的符号版本必须找得到、加载得上。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











