问题描述
项目中准备引入redis,采用acl的c++库对redis进行访问。acl的示例代码如下所示
#include
对示例代码进行编译链接
`
报了许多链接的错误
(aio_listen_stream.o
问题分析
acl和acl_cpp均为静态库,acl是最基础的库,以C语言实现,其它库均依赖于该库; acl_cpp库用C++封装了acl库,提供给C++程序调用。
链接错误集中表现为acl_cpp库引用了acl库中的函数但未能找到其定义。
问题解决
在编译命令的参数中已给出了acl库的路径和名称,不应该找不到。尝试把acl_cpp库在命令行中的顺序放在acl库之前
`
顺利编译通过。
原理探究
创建一个示例工程,包含main.c、comp1_func1.c、comp1_func2.c、comp2_func1.c四个文件,其函数调用关系如下所示:
- 编译main.c
0000000000000000 *UND*
main.o中有两个未定义的符号:comp1_func1和comp2_func1
- 编译静态库
0000000000000000 g F .text 000000000000000e comp1_func1
comp1_func2.o: 文件格式 elf64-x86-64
libcomp2.a中有一个未定义的符号comp1_func2
- 增量链接 将main.o和libcomp1.a先进行链接
0000000000000000 l df *ABS*
链接器并不是把静态库文件看做一个整体,而是将打包在其中的目标文件(.o)作为链接单元。在链接过程中,如果某个目标文件中的符号被用到了,那么这个目标文件会单独从库文件中提取出来并入可执行程序,而其余的目标文件则会被丢弃。
main.o中引用了libcomp1.a中comp1_func1.o的comp1_func1函数,因此将comp1_func1.o并入,而comp1_func2.o中的comp1_func2函数未被引用,因此被丢弃。
- 全量链接 将main.o和libcomp1.a、libcomp2.a进行链接
0000000000000000 *UND*
libcomp2.a中引用的comp1_func2函数虽然已在libcomp1.a中定义,但由于comp1_func2.o被丢弃,导致该函数找不到定义
0000000000000021 g F .text 000000000000000e comp1_func1
整个分析的过程可参考下图:
将静态库的顺序调换后,所有符号都找到了定义。所以在链接静态库的时候,应该将被依赖的库放在最右边。