`
把酒泯恩仇
  • 浏览: 26360 次
  • 性别: 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
分享到:
评论

相关推荐

    libjnotify64.so

    jnotify 程序目录中的libjnotify.so是linux32操作系统中的动态链接库, 没有 linux 64操纵系统下 的动态链接库文件,这个是在网上淘到的分享给大家。libjnotify64.so

    linux网路编程 中文 23M 版

    第1 章Linux操作系统概述................... .......................................................................... 2 1.1 Linux发展历史........................................................ 2 ...

    Linux -lglib-2.0 缺失时要用的 arm64下的链接库

    Linux -lglib-2.0 缺失时要用的交叉编译工具链中 arm64下的链接库

    Linux系统中动态链接库的创建及其使用

    编译函数源程序时选用-shared选项即可创建动态链接库,注意应以.so后缀命名,最好放到公用库目录(如/lib,/usr/lib等)下面,并要写好用户接口文件,以便其它用户共享。使用动态链接库,源程序中要包含dlfcn.h头文件,...

    ubuntu16.04源码编译wireshark2.6.10

    打开终端,需要指定临时的环境变量,防止文件找不到动态链接库.so,lib就是wireshark的依赖库。 终端运行: export LD_LIBRARY_PATH=解压后的lib库路径:$LD_LIBRARY_PATH 再次运行wireshark, ./wireshark 如果出错...

    linux静态库与动态库

    linux下面的库文件有两种:静态链接库(xx.a)和动态链接库(xx.so)。 当一个程序使用静态链 接库,那么当link的时候,连接器会把所需要的函数拷贝到源程序里面,这样,当编译完以后,静态链接库就可以不需要了。如果...

    linux下Java视频转码、截图开发包:ffmepg3-opencv-javacpp-javacv-centos6&7

    如果你自己编译、寻找库费了很长时间而不成功,那么,希望这个资源能够帮到你。 里面的jar及linux动态库,由我本人编译、制作,并测试通过。 1、支持centos6(在JDK1.7下编译)和centos7(在JDK1.8下编译)。 2、...

    java class加密保护(完全免费) v2.1

    或者把libclassloader.so拷贝到如“/home/yzj/jdk1.6.0_23/jre/lib/i386/”这jdk的运行目录下, 然后执行java如:java -agentlib:classloader Sample 当然如果class文件没加密,这样运行也不会出错! 应用场合: ...

    基于mediastreamer2的网络电话实现流程以及源码库

    首先接到这一个项目,说是要用mediastreamer2做一个网络电话。之前也是从来没有接触过。于是首先开始在百度中搜索一下需要哪些东西,以及...分析::找不到arm-linux-gnueabi/python2.7/pyconfig.h这文件。那就继续交叉...

    java类加密工具v2.1

    或者把libclassloader.so拷贝到如“/home/yzj/jdk1.6.0_23/jre/lib/i386/”这jdk的运行目录下, 然后执行java如:java -agentlib:classloader Sample 当然如果class文件没加密,这样运行也不会出错! 应用场合: ...

    jni需要注意的常见问题

    jni 输入的问题; 找不到相应的库文件链接的问题java.lang.UnsatisfiedLinkError: no testjni1 in java.library.path ;Linux下编译下找不到库文件符号的问题libXXX.so: undefined symbol: _ZdlPv

    Java类加密工具v2.2(免注册)

    或者把libclassloader.so拷贝到如“/home/yzj/jdk1.6.0_23/jre/lib/i386/”这jdk的运行目录下, 然后执行java如:java -agentlib:classloader Sample 当然如果class文件没加密,这样运行也不会出错! 应用场合:...

    详解Linux动态库生成与使用指南

    在链接动态库生成可执行文件时,并不会把动态库的代码复制到执行文件中,而是在执行文件中记录对动态库的引用。 程序执行时,再去加载动态库文件。如果动态库已经加载,则不必重复加载,从而能节省内存空间。 Linux...

    Linux动态库生成与使用指南

     在链接动态库生成可执行文件时,并不会把动态库的代码复制到执行文件中,而是在执行文件中记录对动态库的引用。  程序执行时,再去加载动态库文件。如果动态库已经加载,则不必重复加载,从而能节省内存空间。 ...

    我心飞扬java类加密工具2.1(亲测可用)

    运行时,要能正确的加载加密后的class文件,必须使用我们提供的动态链接库classloader.dll(windows操作系统)或者libclassloader.so(Linux、Unix操作系统)。执行java时带上参数-agentlib:&lt;动态文件所在路径&gt;\...

    ffmpeg5.0.1安卓全平台so动态库

    本资源基本没有禁用任何功能生成的安卓全平台so,但不支持x264、fdkaac、x265等需要单独编译库。api 29,包含架构armv7-a、armv8-a、x84、x86-64,生成好的包在install目录中。本资源为文章附件资源,原文链接1:...

    ffmpeg6.1.安卓全平台so动态库

    本资源基本没有禁用任何功能生成的安卓全平台so,但不支持x264、fdkaac、x265等需要单独编译库。api 21-34,包含架构armv7-a、armv8-a、x84、x86-64,生成好的包在对应api编号目录中。本资源为文章附件资源,原文链接...

    ffmpeg5.1.4.安卓全平台so动态库

    本资源基本没有禁用任何功能生成的安卓全平台so,但不支持x264、fdkaac、x265等需要单独编译库。api 21-34,包含架构armv7-a、armv8-a、x84、x86-64,生成好的包在对应api编号目录中。本资源为文章附件资源,原文链接...

    Q群云秘书 avbot (聊天机器人).zip

    link=static 表示编译为静态库, runtime-link=static 则表示,应用程序最终会使用静态链接的 C 运行时。这个在 windows 平台是必须的要求。因为 VC 的 C 和 C 运行时打包起来非常麻烦。(mingw 的也一样)linux ...

    个人安装caffe的教训记录.txt

    一不小心把Ubuntu14升级到了16,折腾了好几天才把caffe安装上,建议在Ubuntu14的基础上进行安装,如果caffe官方能够支持16或者以上的版本就更好了。。。 我的环境是anaconda3+cuda10.1 首先应该安装opencv,试了...

Global site tag (gtag.js) - Google Analytics