背景
最近出现了一个问题,在执行第三方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/