strip仅删调试信息,必须配合-ffunction-sections、-fdata-sections、-wl,--gc-sections及-flto才能剔除未用符号;否则导出符号和死代码仍残留。

直接结论:只做 strip 是无效瘦身,必须配合 -ffunction-sections + -fdata-sections + -Wl,--gc-sections 和 -flto 才能真正剔除未用符号;否则 strip 只删调试信息,导出符号和死代码全留着。
为什么 strip 后体积没怎么变?
常见现象是执行 strip --strip-debug your_binary 后,ls -lh 显示大小几乎不变。这是因为:
-
strip --strip-debug只移除.debug_*段,不影响.text、.data或动态符号表.dynsym - 大量未调用的函数、模板实例、虚函数表仍驻留在
.text中——链接器默认把所有函数塞进一个大段,没法单独删 - 若用了
dlsym或函数指针间接调用,且没加__attribute__((used)),这些函数还可能被--gc-sections误删,导致运行时崩溃
必须同时启用的三编译+一链接选项
这是裁剪未用代码的最小有效组合,缺一不可:
-
-ffunction-sections:每个函数生成独立段(如.text.foo、.text.bar) -
-fdata-sections:每个全局变量/静态变量也分段(如.data.config_buf) -
-Wl,--gc-sections:链接时扫描引用关系,只保留可达段 - 必须搭配
-Os(非-O2或-O3),否则内联过度会制造更多“看似有用”的函数段
在 CMake 中写法示例:
组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Os -ffunction-sections -fdata-sections")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
LTO 能否替代 --gc-sections?
不能,LTO(-flto)和 --gc-sections 解决的是不同层级的问题:
-
-flto=thin(推荐)或-flto:让链接器看到跨 .o 文件的调用链,从而合并重复模板实例、内联跨文件函数、消除整程序级死代码 -
--gc-sections:只管段粒度的存活判断,不分析函数逻辑;但它是 LTO 前置条件——没有分段,LTO 也没法精准回收 - 实测中二者叠加可比单用减少额外 10–15% 体积,尤其对泛型-heavy 的项目(如含大量
std::vector<t></t>实例)效果明显
注意:-flto 要求整个项目统一开启(包括所有依赖静态库),否则链接失败;且需确保所有 .a 库也是 LTO 编译生成的。
容易被忽略的符号残留点
即使上述都配齐,以下几处仍常藏有几百 KB 冗余:
-
readelf -d your_binary | grep NEEDED查看动态依赖——若出现libz.so.1或libstdc++.so.6,说明你本想静态链接却意外连了动态库 -
nm -C --defined-only your_binary | grep -v " U "列出所有定义符号,重点搜std::开头的函数——大量未用 STL 辅助函数(如std::string::_M_construct)可能因隐式实例化残留 - RTTI 和异常表:必须显式加
-fno-rtti -fno-exceptions,否则typeinfo名字和.eh_frame段无法被--gc-sections处理
最终验证是否生效:对比 arm-none-eabi-size --format=SysV your.elf 中 text 段变化,而非只看文件总大小——这才是真实代码体积。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










