链接顺序导致弱符号覆盖强符号的问题及解决办法问询
解决弱符号库先链接时强符号被忽略的问题
问题背景
现有三个文件:
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 - 版本脚本标记强符号:
- 为
libstrong.so创建版本脚本strong.version:{ global: foo; local: *; }; - 重新编译
libstrong.so:g++ strong.cc -o libstrong.so -shared -fPIC -Wl,--version-script=strong.version - 链接时指定强符号版本:
g++ main.o -L. -lweak -lstrong -Wl,--defsym=foo=foo@BASE
- 为
内容的提问来源于stack exchange,提问作者Islam Ashraf
相关产品推荐
相关产品推荐

