本文讨论了linux动态库 静态库中函数的覆盖问题。
测试目的:
同名函数,分别打成动态库libdync_lib.so与静态库libstatic_lib.a,并把libstatic_lib.a打到另一个动态库libapi.so中,
在可执行程序中分别连接libdync_lib.so与libapi.so,此时到底调用的是哪个库中的函数?
测试结论:
不同库中的同名函数会被覆盖,后链接的库中的同名函数会被先前库覆盖。
测试方法:
static_lib.h
1 void print();
static_lib.cpp
1 #include <cstdio.h> 2 #include "static_lib.h" 3 4 void print() 5 { 6 printf("i am static print "); 7 }
dync_lib.h
1 void print();
dync_lib.cpp
#include <cstdio.h> #include "dync_lib.h" void print() { printf("i am dync print "); }
api.h
void func();
api.cpp
1 #include "static_lib.h" 2 3 void func() 4 { 5 print(); 6 }
main.cpp
#include <api.h> int main() { func(); print(); return 0; }
制作libdync_lib.so动态库
g++ dync_lib.cpp -shared -fPIC -o libdync_lib.so
制作libstatic_lib.a静态库
g++ -c static_lib.cpp -share -fPIC -o static_lib.o
ar crv libstatic_lib.a static_lib.o
制作libapi.so动态库,其依赖静态库libstatic_lib.a
g++ api.cpp -shared -fPIC -o libapi.so -lstatic_lib
有三种方式生成可执行程序
1、g++ main.cpp -lapi -o main
2、g++ main.cpp -lapi -ldync_lib -o main
3、g++ main.cpp -ldync_lib -lapi -o main
每种方式都能执行成功,但输出不一样,
1、2执行时,输出一致:
i am static print
3执行时,输出;
i am dync print
下面分析原因:
1、第一种方式中,main.cpp中只包含了 api.h,而api.h中并没有定义print函数,那么main中怎么找到了该函数并且调用成功了呢?
因为,生成libapi.so时连接了libstatic_lib.a,而其中包含print,也就是说,静态库中的函数符号都会被打到动态库中,所以main能找到print函数的实现,来自libstatic_lib.a。
2、后2种方式中,只是额外链接libdync_lib.so,但链接的顺序不同。从结果中看,程序正常执行。
第二种方式调用的是libstatic_lib.a中的print函数,对比发现,第三种调用的是libdync_lib.so中的print。
也就是说,根据链接的顺序,先被链接的库中的符号(函数)会覆盖后面库中的同名符号。