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

GNU链接器不再覆盖Weak symbols?多定义错误疑问

关于同名全局变量链接报错的原因及解决方法

首先要纠正一个概念:你代码里的int x;属于tentative definition(暂定定义),并非weak symbol(弱符号)。弱符号需要通过__attribute__((weak))显式声明,两者是完全不同的概念。

为什么现在会报错?

《深入理解计算机系统》(CSAPP)7.6节描述的是C89标准下的传统链接行为:当时C语言允许多个文件中的暂定定义(未初始化的全局变量)被当作common symbol处理,链接器会自动合并这些符号,最终只保留一个实例。

但从C99标准开始,规则发生了变化:暂定定义会被视为regular definition(常规定义)(强符号)。而GCC从较新版本开始(比如你使用的11.3.0),默认采用C99及之后的标准模式,此时多个强符号同名就会触发链接器的「multiple definitions」错误——这是符合新C标准的行为,并非特性变更,而是默认编译标准的切换。

如何恢复CSAPP中的行为?

如果需要让链接器回到合并common symbol的旧行为,可以使用GCC的-fcommon编译选项:

gcc -fcommon b1.c b2.c

这样两个文件中的int x;会被当作common symbol处理,链接时自动合并为一个变量,不会报错。

其他合规的解决方式

  1. 显式声明extern:在其中一个文件中将变量改为引用而非定义,比如修改b2.c:
    // b2.c
    extern int x; // 仅引用b1.c中定义的x,不创建新符号
    
  2. 使用弱符号:如果确实需要利用弱符号特性,显式声明其中一个变量为弱符号:
    // b2.c
    int __attribute__((weak)) x; // 弱符号,链接时优先使用b1.c中的强符号x
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 14:25:19