当前位置:   article > 正文

Linux动态库与静态库同名函数链接顺序问题_同名函数, 一份来自 静态库, 一份来自代码,

同名函数, 一份来自 静态库, 一份来自代码,

1. 调用过程

main(主程序) --> calltest()函数 (libcalltest.so) --> funtest()函数

funtest()函数有两个地方实现,动态库是weak类型的实现,静态库是默认类型。期望是可以屏蔽掉动态库里的实现,调用到静态库中,但实际调用和链接顺序有关。

  • 动态库:libfuntest.so (weak类型
[func]$ nm -D libfuntest.so 
0000000000000685 W funtest
  • 1
  • 2
  • 静态库:
[func]$ nm -A libstfunctest.a 
libstfunctest.a:stfunctest.o:0000000000000000 T funtest
  • 1
  • 2

2. 代码实现

  1. main.c
#include <stdio.h>
#include <stdlib.h>

extern void calltest();
int main(void)
{
        calltest();
        return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  1. calltest.c
#include <stdlib.h>
#include <stdio.h>

extern void funtest();
void calltest (void)
{
        printf("This is calltest, call funtest\n");
        funtest();
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

编译libcalltest.so

gcc -fPIC -c calltest.c -o libcalltest.o
gcc -shared -o libcalltest.so libcalltest.o
或
gcc -fPIC -shared calltest.c -o libcalltest.so
  • 1
  • 2
  • 3
  • 4
  1. stfunctest.c
#include <stdlib.h>
#include <stdio.h>

void funtest (void)
{
        printf("This is a funtest\n");
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

编译libstfunctest.a

gcc -c stfunctest.c -o stfunctest.o
ar rc libstfunctest.a stfunctest.o
  • 1
  • 2
  1. funtest.c
#include <stdlib.h>
#include <stdio.h>

#define weak_alias(name, aliasname) _weak_alias (name, aliasname)
#define _weak_alias(name, aliasname) \
  extern __typeof (name) aliasname __attribute__ ((weak, alias (#name)));

void __funtest (void)
{
        printf("This is so funtest\n");
}
weak_alias (__funtest, funtest)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

编译libcalltest.so

gcc -fPIC -c funtest.c -o libfuntest.o
gcc -shared -o libfuntest.so libfuntest.o
  • 1
  • 2

3. 链接验证

动态库路径:

export LD_LIBRARY_PATH=/home/test/func:$LD_LIBRARY_PATH
  • 1
  1. 仅有这个顺序调用静态库中函数:-lcalltest -lstfunctest -lfuntest
[func]$ gcc main.c -L. -lcalltest -lstfunctest -lfuntest
[func]$ ./a.out 
This is calltest, call funtest
This is a funtest
  • 1
  • 2
  • 3
  • 4
  1. 其余情况都调用的so中的weak函数
[func]$ gcc main.c -L. -lfuntest -lstfunctest -lcalltest
[func]$ ./a.out 
This is calltest, call funtest
This is so funtest
[func]$ gcc main.c -L. -lstfunctest -lfuntest -lcalltest
[func]$ ./a.out 
This is calltest, call funtest
This is so funtest
[func]$ gcc main.c -L. -lstfunctest -lcalltest -lfuntest
[func]$ ./a.out 
This is calltest, call funtest
This is so funtest
[func]$ gcc main.c -L. -lcalltest -lfuntest -lstfunctest
[func]$ ./a.out 
This is calltest, call funtest
This is so funtest
[func]$ gcc main.c -L. -lfuntest -lcalltest -lstfunctest
[func]$ ./a.out 
This is calltest, call funtest
This is so funtest
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

4. 原因总结

默认情况下,对于未使用到的符号,链接器不会将它们链接进共享库和可执行程序,也就是默认参数为-Wl,-no-whole-archive
综上,想要静态库-lstfunctest被链接进去,第一个链接的库必须是调用库-lcalltest,链接器才知道有对应的符号需要被链接。其次静态库-lstfunctest必须在动态库-lfuntest之前;否则先链接的动态库中符号,之后因为已链接符号则不会再把静态库链接进来。
也可以改成将静态库符号全部链进来:

gcc main.c -L. -Wl,--whole-archive -lstfunctest -Wl,--no-whole-archive -lcalltest -lfuntest
  • 1
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/盐析白兔/article/detail/492435
推荐阅读
相关标签
  

闽ICP备14008679号