编译过程中目标文件和静态库文件的重名冲突问题

本文探讨了在将第三方库整合到工程项目中时遇到的符号冲突问题,并详细解释了如何使用GCC编译器选项-Wl,--whole-archive和-Wl,--no-whole-archive来定位并解决这类冲突。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

背景

最近出现了一个问题,在执行第三方demo程序的之后,程序正常,把demo整合到自己工程,我们的工程里面有很多文件和库
编译通过,但是运行之后,不正常。
把demo前移到main去执行,也不正常;
程序运行后,只跑demo相关的代码也不正常;
又把demo独立编译成.o,再去链接工程的其他.o,还是不正常;
demo.o不去链接工程的其他.o,工作正常。
 
后面猜测是同名异常导致第三方库工作不正常。主要用到了这两个参数需要用到-Wl,--whole-archive和 -Wl,--no-whole-archive
 
 
如何定位重名冲突

静态库和.o文件的链接过程
.o文件的是全部注入到程序中
.a 静态库文件按需注入,也就是说当.o文件没有的,才会到.a中找,如果有,则不找。
 
如果存在以下文件
test1.c

#include <stdio.h>
int aa(){
        printf("test1\n");
        return 0;
}


test2.c

#include <stdio.h>
int aa(){
        printf("test2\n");
        return 0;
}


test.c

#include <stdio.h>
 
int aa();
int main(){
        aa();
        return 0;
}


1、从文件中,我们可以看到test1.c 和 test2.c 中都实现aa函数,那如果这几个文件先编译成.o,再链接时会出现什么问题?
gcc -c test.c
gcc -c test1.c
gcc -c test2.c
gcc test1.o test2.o test.o -o test

编译器会告诉我们aa被多次定义了
 


2、如果test1被编译成静态库,编译再链进来会怎样呢?
ar -rc libtest1.a test1.o
gcc test.o test2.o -o test -static libtest1.a

我们会发现,其实链的是test2中的aa,这就是按需链接,因为.o已经有了,则不需要.a中的
 
那么问题来了,如果test1中也调用了aa呢?
 
那其实链接的也是test2中的aa,因为aa已经被记录为defined了。
 
假设,test1是第三方库,test2是我们自己的库,则出现了第三方库调用了我们内部库,导致一些异常。
 
3、如何确定,我们的库和第三方库有没有重名呢?
 
需要用到-Wl,--whole-archive和 -Wl,--no-whole-archive
-Wl,--whole-archive: 编译时,把这个参数后面的静态库,以.o文件的形式全部链进来
-Wl,--no-whole-archive:用来取消-Wl,--whole-archiv的作用
 
也就是说-Wl,--whole-archiv和-Wl,--no-whole-archive中间放置我们的第三方库,这样的话第三方库就会.o形式全部加载,而.o在加载的时候,会判断重名冲突

从上面我们通过工具判断我们的工程和第三方库有命名冲突,从而定位出异常问题


 
参考资料

https://blog.youkuaiyun.com/u012927281/article/details/50573243
https://tonybai.com/2010/10/11/start-with-mock-malloc/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值