`
把酒泯恩仇
  • 浏览: 27109 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

#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 文件

  1. int plus(int a, int b)  
  2. {  
  3.     return a + b;  
  4. }  

编译成动态链接库

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

产生动态链接库libfoo.so
另外写一个main.c文件

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

现在开始思考如何存放libfoo.so位置?

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

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

出现以下提示:

baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ls
libfoo.so  main.c  plus.c
baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ 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$ export LIBRARY_PATH="."
baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ gcc main.c -o main -lfoo
baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ls
libfoo.so  main  main.c  plus.c

恭喜,成功找到了.
那好,如果此时我们运行代码

baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ./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$ export LD_LIBRARY_PATH=".":$LD_LIBRARY_PATH
baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ls
libfoo.so  main  main.c  plus.c
baiyang@baiyang-Lenovo-G450:~/workspace/test_so$ ./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

熟练掌握它们,会对系统跟进一步的认识,加油吧.

额外资料

 

-----------------打造高质量的文章 更多关注 把酒泯恩仇---------------

为了打造高质量的文章,请  推荐  一下吧。。。。谢谢了,请关注我后续的文章,会更精彩哦

请关注sina微博:http://weibo.com/baiyang26

把酒泯恩仇官方博客:http://www.ibaiyang.org 【推荐用google reader订阅】

把酒泯恩仇官方豆瓣:http://www.douban.com/people/baiyang26/

如果您想转载本博客,请注明出处

如果您对本文有意见或者建议,欢迎留言

1
0
分享到:
评论

相关推荐

    linux 下 libssl.so.10 libcrypto.so.10

    如果系统找不到这两个库,可能会导致依赖它们的程序无法正常运行,出现“找不到符号”(`undefined symbol`)之类的错误。 此外,需要注意的是,`libssl.so.10`和`libcrypto.so.10`是特定版本的库文件,随着OpenSSL...

    linux下编译.so库文件

    在Linux系统中,库文件分为静态库和动态库两大类,它们分别以`.a`和`.so`作为文件扩展名,服务于不同的编译链接需求。 - **静态库**:通常包含多个`.o`目标文件的集合,用于在编译时链接到应用程序中。这意味着在...

    LINUX动态库.so嵌套.so文件

    在Linux系统中,动态库(.so文件)是程序运行时加载的共享对象,它们提供了函数和数据供其他程序调用。"LINUX动态库.so嵌套.so文件"的主题涉及了如何在一个动态库中嵌入另一个动态库,这种技术通常用于代码重用和...

    libldap.so.2、liblber.so.2等linux系统缺少的库文件完整版

    这些库文件在某些Linux发行版(如CentOS 5.x)中可能不默认安装,因此如果尝试运行依赖这些库的软件时,系统可能会报告错误。 `libldap.so.2`是OpenLDAP库的主要部分,它实现了LDAP客户端接口,提供了与LDAP服务器...

    Tess-two编译可用.so文件 2018

    使用这些文件时,开发者需要确保它们与目标设备的架构匹配,否则应用可能无法正常运行。同时,对于支持64位设备的应用,根据Google的政策,必须包含64位的.so文件。 总的来说,Tess-two编译的.so文件是Android OCR...

    linux下java环境gdal编译好的文件

    静态库则在编译时链接,不需要运行时的额外配置。 总的来说,这个压缩包提供了一套完整的GDAL环境,包括Java接口、坐标系统转换工具和必要的库文件,使得在Linux上进行地理空间数据处理的Java开发变得更为便捷。...

    CentOS7下的libcrypto.so.6+libexpat.so.0+libssl.so.6文件

    这些软件包不仅会提供所需的库文件,还会包含必要的头文件,以便于编译链接依赖这些库的源代码。 总之,`libcrypto.so.6`、`libssl.so.6`和`libexpat.so.0`是Linux系统中至关重要的动态链接库,分别涉及加密操作、...

    QNX系统中添加自己编译的.so库.zip_QNX .so文件_SO打包_qnx文件_qnx系统g++编译_so库

    6. **修改build配置文件**:为了将自编译的.so库添加到QNX系统,你需要更新构建脚本或Makefile,确保链接器知道新的库位置,并且在运行时能够找到它。可能需要设置-L参数指定库路径,-l参数指定库名。 7. **部署到...

    opencv-4.5.5编译后的jar包和linux平台的so文件

    其次,`libopencv_java455.so` 是一个动态链接库文件,它是OpenCV库在Linux平台上的实现。在Linux系统中,`.so` 文件是共享对象(Shared Object),相当于Windows系统中的`.dll` 文件。这个特定的文件是OpenCV的Java...

    Linux动态链接库.so文件的创建与使用

    静态链接是在编译时将所有库函数直接嵌入到可执行文件中,而动态链接则是在运行时才加载所需的库。动态链接库的主要优点包括节省磁盘空间和内存,因为多个程序可以共享同一库的实例。 创建`.so`文件的过程通常涉及...

    libsigar-amd64-linux.so和libsigar-x86-linux.so

    在Linux环境下,libsigar提供了两个针对不同处理器架构的动态链接库:libsigar-amd64-linux.so是专为64位AMD(Advanced Micro Devices)处理器设计的,而libsigar-x86-linux.so则服务于32位的x86处理器。这两个库...

    libsigar-amd64-linux.so libsigar-x86-linux.so

    遇到找不到库文件的错误时,需要确保这些文件位于Java能够找到的路径中,或者正确设置`java.library.path`。使用Sigar库可以帮助开发者实现强大的系统监控功能,跨越不同的操作系统和硬件架构。

    libstdc++.so.6.0.25zip.zip

    在64位系统中,库文件通常存储在/usr/lib64/目录下,而链接到这些库的程序则通过LD_LIBRARY_PATH环境变量或在编译时指定的-rpath选项来找到它们。对于libstdc++.so.6,系统会查找名为libstdc++.so.6的符号链接,该...

    linux创建和使用动态链接库.so文件

    有时,即使链接成功,程序也可能因找不到动态链接库而无法运行。这可能是由于系统不知道去哪里查找库文件导致的。解决这个问题的方法有两种: 1. **修改 `/etc/ld.so.conf` 文件**:在该文件中添加动态链接库所在的...

    MuPDF1.2编译生成的libmupdf.so文件

    10. **调试与优化**:如果编译过程中遇到问题,比如链接错误、找不到头文件等,需要检查配置文件和环境设置。编译完成后,为了提高性能和减少内存占用,可能还需要对生成的库进行进一步的优化。 总结来说,`...

    libsqlite.so linux 交叉编译 arm

    标题“libsqlite.so Linux 交叉编译 ARM”指的是在Linux环境下,使用交叉编译技术为ARM架构的设备编译SQLite动态链接库的过程。SQLite是一个轻量级的、自包含的、开源的关系型数据库引擎,广泛应用于嵌入式系统,如...

    linux下libtinfo.so.5函数!!!!

    当在Linux环境中运行程序时,如果系统找不到所需的动态链接库,程序将无法启动,这时会报出类似于“未找到libtinfo.so.5”这样的错误。解决这个问题通常有以下几种方法: 1. **安装对应的库**:通过包管理器(如`...

    MuPDF1.0编译生成的libmupdf.so文件

    6. **集成到Android应用**:编译完成后,将生成的`libmupdf.so`文件放入Android项目的`jniLibs`目录下,对应的架构子目录(如`armeabi-v7a`或`arm64-v8a`)。然后在应用中通过Java Native Interface (JNI) 调用库中...

    libstdc++.so.6: 无法打开共享对象文件: 没有那个文件或目录

    3. **链接问题**:`libstdc++.so.6`可能被软链接到了其他版本的文件,导致程序无法正确加载。 #### 解决方案 为了解决上述问题,可以按照以下步骤进行操作: 1. **确认版本一致性**: - 首先,需要确认运行的...

    libc.so.6 libc.so.6

    与静态链接库不同,静态链接库会在编译时将所需的库函数合并到可执行文件中,而动态链接库则是在程序运行时由操作系统负责加载。 二、libc.so.6详解 `libc.so.6`是Glibc(GNU C Library)的一个版本标识,Glibc是...

Global site tag (gtag.js) - Google Analytics