4

Linux出错error while loading shared libraries:提示找不到xx.so文件

 3 years ago
source link: https://www.huhexian.com/14085.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Linux出错error while loading shared libraries:提示找不到xx.so文件

2021-11-3014:15:38评论2734字

在Linux服务器上,应该会有很多人遇到过这种问题吧,在我们编译文件的时候,提示错误:“error while loading shared libraries:提示找不到xx.so文件”,对于一些新手来说,xx.so文件是什么文件可能都不知道是什么,那么xx.so文件是什么?有什么用?如何解决找不到xx.so文件。下面就来给大家科普下。

Linux出错error while loading shared libraries:提示找不到xx.so文件

xx.so文件相当与windows上的dll文件,也就是常说的动态链接库。动态链接库是为了减少发布程序的大小,可以将具有相同功能的code放在动态链接库中,随应用程序一起发布。而对于应用程序来说,只需要知道其接口就可以,在运行时动态的加载代码到内存中,与其相反的是静态链接库。

我们在编译的时候提示的错误如下:

  1. baiyang@baiyang-Lenovo-G450:~/Desktop$ ./test_cal_features
  2. ./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进行搜索?

我们来举一个新的例子

新建一个plus.c 文件

  1. int plus(int a, int b)
  2. return a + b;

将其编译成动态链接库

  1. gcc plus.c -o libfoo.so -shared -fPIC

这时候会产生动态链接库libfoo.so,然后我们再写一个main.c文件

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main(int argc, char *argv[])
  4. int sum = plus(3, 5);
  5. printf("%d\n", sum);
  6. return 0;

到这里,我们需要考虑应该如何存放libfoo.so位置?

我们先将libfoo.so存放在当前目录中,进行编译和链接

  1. gcc main.c -o output -lfoo //-lfoo告诉gcc,我们需要动态链接foo库。

编译好会出现下面代码

  1. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ls
  2. libfoo.so main.c plus.c
  3. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ gcc main.c -o main -lfoo
  4. /usr/bin/ld: cannot find -lfoo
  5. collect2: ld returned 1 exit status

这里的提示意思是:gcc不能找到foo库,那么我们如果显示的指示gcc如何搜寻foo呢,我们可以修改LIBRARY_PATH值。

  1. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ export LIBRARY_PATH="."
  2. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ gcc main.c -o main -lfoo
  3. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ls
  4. libfoo.so main main.c plus.c

修改过我们会发现找到了。

如果此时我们再次运行代码

  1. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ./main
  2. ./main: error while loading shared libraries: libfoo.so: cannot open shared object file: No such file or directory

会发现还是遇到开始提到的问题了,那我们怎么看输出到可执行文件main怎么读取libfoo.so呢,在运行过程中到底读的什么文件呢?

这里我们用strace命令来查看到底有什么信号发生

  1. strace ./main

运行后发现它搜索到路径是/lib/i386-linux-gnu,/usr/lib等路径目录下,也就说,是因为没有搜索当前目录,我们继续用以下命令进行修改

  1. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ export LD_LIBRARY_PATH=".":$LD_LIBRARY_PATH
  2. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ls
  3. libfoo.so main main.c plus.c
  4. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ./main

成功运行,用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可以查看可执行文件需要什么链接库。

  1. baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ objdump -x main | grep NEED
  2. NEEDED libfoo.so
  3. NEEDED libc.so.6
  4. VERNEED 0x08048354
  5. VERNEEDNUM 0x00000001

Recommend

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK