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

Red Hat 9下C未初始化数据重叠问题:除-fcommon外的解决方案?

Red Hat 9中多目标文件未初始化数据重叠链接错误的原因与解决方案

问题背景

自Unix/Linux诞生(至少从1970年起),C语言一直支持多个目标文件中的未初始化全局数据对象重叠,即便它们的大小不同。但在Red Hat 9中,这个传统特性出现异常,链接阶段会抛出重复定义的错误。

示例代码

k1.c

char overlay[1024];
int main(int argc, char *argv[]){
    void xmain();
    xmain();
}

k2.c

char overlay[1024];
int xmain(){
}

编译行为差异

  • Red Hat 8编译正常:
[jon@rh8x ~]$ cc k1.c k2.c -o k
  • Red Hat 9编译链接报错:
[jon@rhel9 ~]$ cc k1.c k2.c -o k
/usr/bin/ld: /tmp/ccnCZBZM.o:(.bss+0x0): multiple definition of `overlay'; /tmp/cca4vlOT.o:(.bss+0x0): first defined here
collect2: error: ld returned 1 exit status

使用-fcommon参数可临时解决问题,但该参数不被推荐,且可能在后续GCC版本中被移除。

原因分析

Red Hat 9默认搭载的GCC版本(GCC 10及以上)将-fno-common设为默认编译选项。

在早期GCC版本(如Red Hat 8使用的版本)中,未初始化的全局变量会被放入common段,链接器遇到多个同名的common段变量时,会自动合并它们(即便大小不同,最终取最大的那个的尺寸),这正是传统Unix/C支持的重叠特性。

而-fno-common选项会让未初始化的全局变量直接被放在.bss段,每个目标文件都会生成独立的变量定义,链接器遇到同名的.bss段变量时,就会判定为重复定义并报错。

替代解决方案(除-fcommon外)

  • 显式区分定义与声明:在其中一个文件中保留变量的定义,另一个文件用extern声明变量。比如修改k2.c:
extern char overlay[1024];
int xmain(){
}

若变量大小不同,可使用不指定大小的extern char overlay[];,只要代码的使用逻辑兼容大小差异即可。

  • 使用弱符号:在其中一个文件的变量定义前添加__attribute__((weak))属性,链接器会优先选择非弱符号的定义;如果所有同名变量都是弱符号,则会任选一个(通常取最大的尺寸)。比如修改k2.c:
__attribute__((weak)) char overlay[1024];
int xmain(){
}
  • 跨语言场景适配:对于涉及Fortran、Cobol等语言的场景,需确保不同语言的符号处理逻辑对齐:
    • Fortran中可通过-fno-automatic或特定编译选项控制变量的common属性;
    • Cobol可调整编译选项让未初始化数据生成符合common机制的符号,或显式声明符号的链接类型。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 23:37:38