链接、装载和库看完这个系列就够了(四)(符号同名问题)

示例代码

首先贴出代码:

//lib_fun1.c 
#include <stdio.h>
#include "lib_fun1.h"
int fun()
{
        printf("in lib_fun1\n");
        return 0;
}
int fun1()
{
        fun();
        return 0;
}
//lib_fun2.c 
#include <stdio.h>
#include "lib_fun2.h"
int fun()
{
        printf("in lib_fun2\n");
        return 0;
}

int fun2()
{
        fun();
        return 0;
}
//cat main.c 
#include "lib_fun1.h"
#include "lib_fun2.h"

int main()
{
        fun1();
        fun2();
        return 0;
}
//main.c 
#include "lib_fun1.h"
#include "lib_fun2.h"

int main()
{
        fun1();
        fun2();
        return 0;
}
#Makefile 
all:main_so main_static main_all1 main_all2

lib_so1.so: lib_fun1.o
        gcc -shared -o $@ $<
lib_so2.so: lib_fun2.o
        gcc -shared -o $@ $<
lib_a1.a: lib_fun1.o
        ar rcs $@ $<
lib_a2.a: lib_fun2.o
        ar rcs $@ $<

main_so: main.o lib_so1.so lib_so2.so
        gcc -o $@ main.o -l_so1 -l_so2 -L. -Wl,--rpath=.

main_static: main.o lib_a1.a lib_a2.a
        gcc -o $@ main.o -l_a1 -l_a2 -L.

main_all1: main.o lib_a1.a lib_so2.so
        gcc -o $@ main.o -l_a1 -l_so2 -L. -Wl,--rpath=.
main_all2: main.o lib_so1.so lib_a2.a
        gcc -o $@ main.o -l_so1 -l_a2 -L. -Wl,--rpath=.
%.o : %.c
        gcc -fPIC -c $< -o $@

clean:
        rm -rf *.o *.a *.so main_*

对于代码做几点说明:

库的调用采用fun1()和fun2()调用fun()的形式,为什么每个库中直接定义一个fun()函数,这样不是更简单?原因如果每个库中只有fun()函数,这样会导致链接过程中,只链接一个库。读者可以进行尝试,去除fun1()和fun2()函数,发现此时同时链接两个静态库也不会报错(原因可以参考之前的系列讲解),从而影响测试结果。
Makefile中的.c到.o有个选项-fPIC,编译静态库的时候是不需要的,但是这里不影响结果,正常编译静态库的时候应该要去掉。
-Wl,–rpath=.参数可以程序运行时在当前目录查找动态库,这样我们就不需要把动态库复制到/usr/lib目录。
静态库同名
我们看一下两个静态库中的符号同名问题(上面说了,编译静态库的时候不需要添加-fPIC选项):

# make clean;make main_static 
rm -rf *.o *.a *.so main_*
gcc -fPIC -c main.c -o main.o
gcc -fPIC -c lib_fun1.c -o lib_fun1.o
ar rcs lib_a1.a lib_fun1.o
gcc -fPIC -c lib_fun2.c -o lib_fun2.o
ar rcs lib_a2.a lib_fun2.o
gcc -o main_static main.o -l_a1 -l_a2 -L.
./lib_a2.a(lib_fun2.o): In function `fun':
lib_fun2.c:(.text+0x0): multiple definition of `fun'
./lib_a1.a(lib_fun1.o):lib_fun1.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Makefile:16: recipe for target 'main_static' failed
make: *** [main_static] Error 1

我们发现如果静态库同名,会导致链接报错。

动态库同名
然后看一下动态库问题:

# make clean;make main_so 
rm -rf *.o *.a *.so main_*
gcc -fPIC -c main.c -o main.o
gcc -fPIC -c lib_fun1.c -o lib_fun1.o
gcc -shared -o lib_so1.so lib_fun1.o
gcc -fPIC -c lib_fun2.c -o lib_fun2.o
gcc -shared -o lib_so2.so lib_fun2.o
gcc -o main_so main.o -l_so1 -l_so2 -L. -Wl,--rpath=.

链接正常,执行一下程序:

# ./main_so 
in lib_fun1
in lib_fun1

我们发现输出并不正常,原因是输出依赖链接顺序,我们交换一下链接顺序做一下验证:

# gcc -o main_so main.o -l_so2 -l_so1 -L. -Wl,--rpath=.
# ./main_so 
in lib_fun2
in lib_fun2

动态库和静态库同名
我们再看一下动态库和静态库同名的问题:

# make clean;make main_all1;make main_all2
rm -rf *.o *.a *.so main_*
gcc -fPIC -c main.c -o main.o
gcc -fPIC -c lib_fun1.c -o lib_fun1.o
ar rcs lib_a1.a lib_fun1.o
gcc -fPIC -c lib_fun2.c -o lib_fun2.o
gcc -shared -o lib_so2.so lib_fun2.o
gcc -o main_all1 main.o -l_a1 -l_so2 -L. -Wl,--rpath=.
gcc -shared -o lib_so1.so lib_fun1.o
ar rcs lib_a2.a lib_fun2.o
gcc -o main_all2 main.o -l_so1 -l_a2 -L. -Wl,--rpath=.

发现编译正常,看一下输出:

# ./main_all1
in lib_fun1
in lib_fun1
# ./main_all2
in lib_fun2
in lib_fun2

输出并不是依赖于编译顺序,而是依赖于以静态库。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值