编译和链接通过生成可执行文件,但运行时找不到动态库

编译和链接通过生成可执行文件balreport, 但运行时却出现如下的错误:

[wzheng88@bevertec bin]$ balreport -d provident
balreport: error while loading shared libraries: libhpdf-2.1.0.so: cannot open shared object file: No such file or directory
[wzheng88@bevertec bin]$
[wzheng88@bevertec bin]$ which libhpdf-2.1.0.so
/usr/bin/libhpdf-2.1.0.so

动态库文件存在,但程序运行时找不到这个动态库,使用ldd命令:

[wzheng88@bevertec bin]$ ldd balreport
        libhpdf-2.1.0.so =>not found
        libpng12.so.0 => /usr/lib/libpng12.so.0 (0x00879000)
        libclntsh.so.10.1 => /usr/lib/oracle/10.2.0.3/client/lib/libclntsh.so.10.1 (0x03584000)
        libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00d13000)
        libm.so.6 => /lib/tls/libm.so.6 (0x00b14000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00d07000)
        libc.so.6 => /lib/tls/libc.so.6 (0x009dc000)
        libz.so.1 => /usr/lib/libz.so.1 (0x00c3e000)
        libnnz10.so => /usr/lib/oracle/10.2.0.3/client/lib/libnnz10.so (0x0024a000)
        libdl.so.2 => /lib/libdl.so.2 (0x00b0e000)
        libpthread.so.0 => /lib/tls/libpthread.so.0 (0x00c1a000)
        libnsl.so.1 => /lib/libnsl.so.1 (0x00231000)
        /lib/ld-linux.so.2 (0x009c2000)
解决方案:

1. 执行程序前,配一下库的搜索路径:

export LD_LIBRARY_PATH=/usr/local/lib/

2.检查一下/etc/ld.so.conf/里的conf文件,看是否包含/usr/local/lib

有点话,直接?sudo ldconfig更新系统;没有的话讲该路径加入,然后再更新。

 我用第一种方法能够找到库了,但运行时还是原来的错误,我觉得是我的权限不够吧。

网上找到的一些资料:

首先回答前面的问题,一共有多少种方法来指定告诉linux共享库链接器ld.so已经编译好的库libbase.so的位置呢?答案是一共有五种,它们都可以通知ld.so去哪些地方找下已经编译好的c语言函数动态库,它们是:

    1)ELF可执行文件中动态段中DT_RPATH所指定的路径。即在编译目标代码时, 对gcc加入链接参数“-Wl,-rpath”指定动态库搜索路径,eg:gcc -Wl,-rpath,/home/arc/test,-rpath,/lib/,-rpath,/usr/lib/,-rpath,/usr/local/lib test.c

    2)环境变量LD_LIBRARY_PATH 指定的动态库搜索路径

    3)/etc/ld.so.cache中所缓存的动态库路径,这个可以通过先修改配置文件/etc/ld.so.conf中指定的动态库搜索路径,然后执行ldconfig命令来改变。

    4)默认的动态库搜索路径/lib

    5)默认的动态库搜索路径/usr/lib

    另外:在嵌入式Linux系统的实际应用中,1和2被经常使用,也有一些相对简单的的嵌入式系统会采用4或5的路径来规范动态库,3在嵌入式系统中使用的比较少, 因为有很多系统根本就不支持ld.so.cache。

    那么,动态链接器ld.so在这五种路径中,是按照什么样的顺序来搜索需要的动态共享库呢?答案这里先告知就是按照上面的顺序来得,即优先级是:1-->2-->3-->4-->5。我们可以写简单的程序来证明这个结论。

    首先,写成5个函数,这5个函数名称都叫pt,但是里面的内容不一样:

pt1.c

#include <stdio.h>

 

void pt(){

 

        printf("1  path on the gcc give \n");

 

}

 

 

 

pt2.c 

 

#include <stdio.h>

 

void pt(){

 

        printf("2 path on the LD_LIBRARY_PATH \n");

 

}

 

 

 

pt3.c 

 

#include <stdio.h>

 

void pt(){

 

        printf("3 path on the /etc/ld.so.conf \n");

 

}

 

 

 

pt4.c 

 

#include <stdio.h>

 

void pt(){

 

        printf("4 path on the /lib \n");

 

}

 

 

 

pt5.c 

 

#include <stdio.h>

 

void pt(){

 

        printf("5 path on the /usr/lib \n");

 

}

 

 

 

    然后,分别编译这5个函数,然后将它们分别移到上面5种情况对应的5个不同目录下:

 

gcc -fPIC -c pt1.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /tmp/st/1/

 

gcc -fPIC -c pt2.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /tmp/st/2/

 

gcc -fPIC -c pt3.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /tmp/st/3/

 

gcc -fPIC -c pt4.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /lib/

 

gcc -fPIC -c pt5.c -o pt.o

gcc -shared pt.o -o libpt.so

mv libpt.so /usr/lib/

 

    再次,编写一个main函数m,让它来调用函数pt:

m.c

#include <stdio.h>

 

 

int main(){

        printf("start....\n");

        pt();

        printf("......end\n");

        return 0;

}

 

    最后,准备环境,让ld都知道这5个路径:

(a) 往/etc/ld.so.conf总增加一行,内容:/tmp/st/3,然后执行 ldconfig 命令

(b) export LD_LIBRARY_PATH=/tmp/st/2

另外3中路径,ld都可以得到,请接着看下面。

    之后测试:

gcc m.c -o m1 -L/tmp/st/1 -lpt -Wl,-rpath,/tmp/st/1

./m1

start....

1  path on the gcc give

......end

这里在可执行文件中动态段中DT_RPATH所指定的路径,因此需要在编译m.c的时候就指定路径,由于其他路径都也告诉了ld,很明显,此种方法优先级最高了。

 

gcc m.c -o m -L/tmp/st/1 -lpt

./m

start....

2 path on the LD_LIBRARY_PATH

......end

这里很显然调用了LD_LIBRARY_PATH指定了路径中的共享库,因此此种情况优先级第二。

 

mv /tmp/st/2/libpt.so /tmp/st/2/libpt2.so

/m

start....

3 path on the /etc/ld.so.conf

......end

这里是调用了/etc/ld.so.cache中所缓存的动态库路径中的共享库,因此此种情况优先级第三。

 

mv /tmp/st/3/libpt.so /tmp/st/3/libpt3.so

./m

start....

4 path on the /lib

......end

这里是调用/lib中的共享库,优先级第四。

 

rm /lib/libpt.so

./m

start....

5 path on the /usr/lib

......end

这里是调用/lib中的共享库,优先级第五。

http://blog.sina.com.cn/s/blog_690c46500100kxhd.html

另一个的链接:

http://www.360doc.com/content/12/0313/10/8093902_193931244.shtml

 

 

    故证明这五种路径指定方法的优先级是1-->2-->3-->4-->5!

 

 

转载于:https://www.cnblogs.com/wzheng/p/3487934.html

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,我来为你简单介绍一下如何设置编译生成执行文件、使用 CMake 进行构建、以及如何进行静态链接和动态链接。 1. 主函数编译生成执行文件 在主函数编写完成后,使用命令行编译工具或者集成开发环境(IDE)进行编译生成可执行文件。以 gcc 编译器为例,编译命令如下: ``` gcc main.c -o main ``` 其中 main.c 是主函数源代码文件,main 是生成可执行文件名。 2. 使用 CMake 进行构建 使用 CMake 进行构建可以提高开发效率,方便在不同的平台和编译器上进行编译和构建。在项目根目录下创建 CMakeLists.txt 文件,并在其中定义项目名称、源代码文件可执行文件等信息。示例 CMakeLists.txt 文件如下: ``` cmake_minimum_required(VERSION 3.0) project(my_project) add_executable(my_project main.c) ``` 其中,cmake_minimum_required 表示 CMake 的最低版本要求,project 定义项目名称,add_executable 定义可执行文件名和源代码文件。 3. 静态链接和动态链接 静态链接和动态链接都是将中的代码和数据与可执行文件关联起来。静态链接是将代码和数据复制到可执行文件中,而动态链接是在程序运行时动态加载。 静态链接可以通过在编译时使用 -static 选项来进行,示例编译命令如下: ``` gcc main.c -static -o main ``` 动态链接可以通过在编译时不使用 -static 选项来进行,示例编译命令如下: ``` gcc main.c -o main ``` 以上是简单的设置方法,具体设置还需要根据不同的编译器和操作系统进行调整。希望这些信息对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值