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

链接顺序导致弱符号覆盖强符号的问题及解决办法问询

解决弱符号库先链接时强符号被忽略的问题

问题背景

现有三个文件:

  • strong.cc(定义强符号foo)
    #include <stdio.h>
    void foo(){
       printf("Strong is here\n");
    }
    
  • weak.cc(定义弱符号foo)
    #include <stdio.h>
    void __attribute__((weak)) foo();
    void foo(){
       printf("Weak is here\n");
    }
    
  • main.cc(调用foo)
    #include <stdio.h>
    extern void foo();
    int main(int argc, char* argv[]) {
       foo();
       return 0;
    }
    

编译生成动态库后,必须按-lweak -lstrong的顺序链接,但默认会输出Weak is here,需要强制调用libstrong.so中的强符号foo。

核心原因

链接器按库的处理顺序解析符号:先处理libweak.so时,其弱符号foo会被绑定为main.o中foo引用的决议结果;后续处理libstrong.so时,强符号foo因符号已被解析,不会替换已绑定的弱符号。

解决方案

方法1:使用--strong-symbol-precedence链接选项(推荐)

GNU ld 2.35及以上版本新增了--strong-symbol-precedence选项,强制链接器优先选择强符号,无论库的链接顺序。链接命令修改为:

g++ main.o -L. -lweak -lstrong -Wl,--strong-symbol-precedence

执行后程序会输出Strong is here,直接解决问题。

方法2:低版本ld兼容方案

若你的GNU ld版本低于2.35,可通过以下方式绕过:

  • 修改代码强制未解析符号:
    在main.cc中修改foo的声明:
    extern void foo() __attribute__((externally_visible));
    
    链接时用-u foo强制foo保持未解析状态,直到所有库处理完成:
    g++ main.o -L. -u foo -lweak -lstrong
    
  • 版本脚本标记强符号:
    1. 为libstrong.so创建版本脚本strong.version:
      {
        global: foo;
        local: *;
      };
      
    2. 重新编译libstrong.so:
      g++ strong.cc -o libstrong.so -shared -fPIC -Wl,--version-script=strong.version
      
    3. 链接时指定强符号版本:
      g++ main.o -L. -lweak -lstrong -Wl,--defsym=foo=foo@BASE
      

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 22:15:26