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

如何移除C语言BSS恢复段中未使用的数据?

未使用BSS段未被--gc-sections剥离的原因及解决办法

核心原因

1. 符号被隐式引用

即便你没有直接调用某个BSS变量,编译器或链接器仍可能判定该符号被引用:

  • 开启-g调试编译时,生成的符号表会保留所有符号的关联关系,干扰链接器对"未使用"的判断。
  • 动态链接场景下,PLT/GOT表会为全局符号自动生成条目,哪怕符号未被实际调用,链接器也会保留对应BSS段。
  • 低优化等级下,编译器生成的辅助代码(比如全局构造/析构函数的注册逻辑)可能间接引用BSS变量,导致段无法被剥离。

2. 链接脚本的合并行为

多数默认链接脚本会将所有.bss.*子段合并为一个全局.bss段。一旦合并完成,--gc-sections无法单独剥离其中未使用的部分——链接器只会对独立的section做GC判定,而非合并后段内的单个变量。

3. 低优化等级的限制

使用-O0编译时,编译器不会进行死代码消除,也不会生成清晰的符号使用标记。链接器无法准确识别未被使用的BSS变量,自然不会剥离对应段。

解决措施

1. 调整编译优化与符号可见性

  • 改用-O1及以上优化等级(推荐-O2),让编译器主动消除未使用变量,并生成明确的符号使用标记。
  • 动态链接场景配合-fvisibility=hidden编译标志,隐藏未导出的符号,避免PLT/GOT表生成不必要条目,帮助链接器精准判断未使用段。

2. 自定义链接脚本

修改链接脚本,避免提前合并BSS子段,示例片段如下:

SECTIONS {
  /* 保留其他段的原有定义 */
  .bss : {
    *(.bss .bss.*)
    *(COMMON)
  }
  /* 不使用*(.bss)这类合并写法,保留.bss.*子段的独立性 */
}

同时可在脚本中为目标section添加!keep属性,明确允许链接器剥离未使用部分。

3. 排查隐式引用来源

  • 添加-Wl,--print-gc-sections链接标志,打印被GC的段列表,对比未被剥离的BSS段,定位隐式引用的源头。
  • 临时关闭调试信息(去掉-g)后重新编译,验证是否是调试符号导致的问题。

4. 静态链接场景的特殊处理

如果是静态链接,确保静态库同样使用-ffunction-sections -fdata-sections编译,这样链接器才能对静态库内的单个section做GC判定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 15:22:32