strip 命令对 Linux/macOS 的 ELF 格式 C++ 编译产物有效,但不支持 Windows PE/COFF;默认仅删 .symtab 和 .strtab,--strip-all 会破坏 dlopen 和调试,--strip-unneeded 更安全;静态库需先 strip 成员对象再归档;编译时用 -fvisibility=hidden 和链接时 --gc-sections 等更彻底;验证需检查 nm -D、readelf -S 等,而非仅看文件大小。

strip 命令对 C++ 编译产物是否有效
有效,但仅限于 ELF 格式目标文件或可执行文件(Linux/macOS)。Windows 的 PE/COFF 文件不能用 strip,得用 llvm-strip 或 editbin /RELEASE。GCC/Clang 默认生成的 Linux 可执行文件、静态库(.a)、共享库(.so)都支持 strip,前提是没加 -g 以外的调试信息保留选项(比如 -gsplit-dwarf 会把调试信息拆到外部文件,strip 不会动它)。
strip 的常用参数与风险点
strip 默认只删符号表(.symtab)和字符串表(.strtab),不影响重定位、动态符号(.dynsym)或函数逻辑。但以下操作容易误伤:
-
strip --strip-all:删掉所有符号,包括.dynsym—— 这会让dlopen失败、gdb完全无法调试、objdump -T看不到导出函数 -
strip --strip-unneeded:相对安全,只删链接时不需要的本地符号(如.text内部的 static 函数),保留.dynsym和动态节区 - 对静态库(
.a)直接strip libxxx.a无效 —— 必须用strip --strip-unneeded *.o先处理每个成员对象,再重新归档
编译阶段就控制符号体积更可靠
比事后 strip 更彻底的方式是在编译/链接时减少符号生成:
- 编译时加
-fvisibility=hidden,再显式用__attribute__((visibility("default")))标记需导出的符号,避免共享库暴露大量内部符号 - 链接时加
-Wl,--exclude-libs,ALL(GCC)或-Wl,-dead_strip(macOS)自动剔除未引用的代码段和符号 - 禁用调试信息:不加
-g,或用-g0;若需部分调试信息,可用-gline-tables-only只保留行号映射 - 避免
-rdynamic(即--export-dynamic),它会把所有全局符号塞进.dynsym,增大体积且无必要
验证 strip 是否生效及残留符号
别只看文件大小变化,重点检查关键符号是否还在:
立即学习“C++免费学习笔记(深入)”;
- 查动态符号(影响运行时加载):
nm -D your_binary或readelf -d your_binary | grep NEEDED - 查是否还有调试节区:
readelf -S your_binary | grep -E '\.(debug|note|comment)'—— 如果存在.debug_*,说明strip没清掉调试信息,得确认是否用了-g编译 - 对比 stripped 前后
size your_binary输出的text/data/bss三段 —— 符号表剥离不影响这些,只减小total行,如果text明显变小,可能是链接器做了 LTO 或 dead code elimination,不是strip干的
真正难处理的是模板实例化、RTTI、异常表这些编译器自动生成的符号,它们藏在 .text 或 .eh_frame 里,strip 删不掉,得靠 -fno-rtti -fno-exceptions 或链接时 --gc-sections 配合 -ffunction-sections -fdata-sections 才能收缩。


















