#LINUX#通过编译链接,却运行时找不到.so文件

我们知道在linux下,.so文件相当与windows上的dll文件,即动态链接库。
动态链接库是为了减少发布程序的大小,可以将具有相同功能的code放在动态链接库中,随应用程序一起发布。而对于应用程序来说,只需要知道其接口就可以,在运行时动态的加载代码到内存中,与其相反的是静态链接库。
在接手一个项目的代码后,因为此代码需要很多第三方库,所以,在本机安装这些第三方库之后,我也成功的通过了编译与链接阶段,生成了可以执行的代码。
可是在运行的时候,出现了以下的错误提示:
baiyang@baiyang-Lenovo-G450:~/Desktop$ ./test_cal_features
./test_cal_features: error while loading shared libraries: libCGAL.so.5: cannot open shared object file: No such file or directory
这里涉及几个问题:
1.为何能通过编译与链接,却不能运行?
2.我明明将libCGAL.so.5,安装到了/usr/local/lib下啊,既然能通过编译与链接,应该能找到啊?
3.执行./test_cal_features时,到底发生了什么事?
4.linux下,应用程序如何对.so进行搜索?
但本质问题,就是linux下gcc搜索路径设置问题.

好,今天就一一来回答以上到问题。
开始一个新的例子
plus.c 文件

int plus(int a, int b)
{
return a + b;
}
编译成动态链接库
gcc plus.c -o libfoo.so -shared -fPIC
产生动态链接库libfoo.so
另外写一个main.c文件

int main(int argc, char *argv[])
{
int sum = plus(3, 5);
printf(“%d\n”, sum);

return 0;  

}
现在开始思考如何存放libfoo.so位置?
开始,我们先将libfoo.so存放在当前目录中,进行编译和链接
gcc main.c -o output -lfoo //-lfoo告诉gcc,我们需要动态链接foo库。
出现以下提示:
baiyang@baiyang-Lenovo-G450:~/workspace/test_so lslibfoo.somain.cplus.cbaiyang@baiyangLenovoG450: /workspace/testso gcc main.c -o main -lfoo
/usr/bin/ld: cannot find -lfoo
collect2: ld returned 1 exit status
也就是说,gcc不能找到foo库,那么我们如果显示的指示gcc如何搜寻foo呢,我们可以修改LIBRARY_PATH值
baiyang@baiyang-Lenovo-G450:~/workspace/test_so exportLIBRARYPATH=.baiyang@baiyangLenovoG450: /workspace/testso gcc main.c -o main -lfoo
baiyang@baiyang-Lenovo-G450:~/workspace/test_so lslibfoo.somainmain.cplus.c.baiyang@baiyangLenovoG450: /workspace/testso ./main
./main: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory
呜呜,遇到开始提到的问题了.
那我们怎么看输出到可执行文件main怎么读取libfoo.so呢,在运行过程中到底读的什么文件呢?
我们可以用strace命令查看到底有什么信号发生
strace ./main
你会发现,它搜索到路径是
/lib/i386-linux-gnu,/usr/lib等路径目录下
也就说,是因为没有搜索当前目录,我们可以通过修改以下命令进行修改
baiyang@baiyang-Lenovo-G450:~/workspace/test_so exportLDLIBRARYPATH=".": LD_LIBRARY_PATH
baiyang@baiyang-Lenovo-G450:~/workspace/test_so lslibfoo.somainmain.cplus.cbaiyang@baiyangLenovoG450: /workspace/testso ./main
8
成功运行,用strace查看存在这一句open(“./libfoo.so”, O_RDONLY|O_CLOEXEC) = 3
故,现在搜索了当前目录。
总结一下,前面提到过的几个环境变量:
LIBRARY_PATH 该环境变量可设置为一个或多个目录名字列表,连接 程序会搜寻该目录,以查找特殊连接程序文件,和由 -l (字母 l )命令行选项指定名字的库。由 -L 命令行选项指定的目录在环境变 量的前面,首先被查找。也见 COMPILER_PATH 。
LD_LIBRARY_PATH 该环境变量不会影响编译程序,但程序运行的时 候会有影响。变量指定一个目录列表,程序会查找该列表定位共享库。 只有当未在编译程序的目录中找到共享库的时候,执行程序必须设置该变量。
那么在默认到情况下,如何进行搜索呢?
动态库的搜索路径搜索的先后顺序是:
1 编译目标代码时指定的动态库搜索路径,LIBRARY_PATH【编译阶段】;
2 在运行时,环境变量LD_LIBRARY_PATH指定的动态库搜索路径【运行阶段】;
3 配置文件/etc/ld.so.conf中指定的动态库搜索路径【编译阶段】;
4 默认的动态库搜索路径/lib【编译阶段】;
5 默认的动态库搜索路径/usr/lib【编译阶段】。## ##
对二进制文件进行处理
strace
gdb
objdump
nm
以上工具,都可以让你查看二进制文件到底干了什么,比如,我们用objdump可以查看可执行文件需要什么链接库
baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ objdump -x main | grep NEED
NEEDED libfoo.so
NEEDED libc.so.6
VERNEED 0x08048354
VERNEEDNUM 0x00000001
熟练掌握它们,会对系统跟进一步的认识,加油吧.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值