zoukankan      html  css  js  c++  java
  • 编译和链接通过生成可执行文件,但运行时找不到动态库

    编译和链接通过生成可执行文件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 ");

    }

    pt2.c 

    #include <stdio.h>

    void pt(){

            printf("2 path on the LD_LIBRARY_PATH ");

    }

    pt3.c 

    #include <stdio.h>

    void pt(){

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

    }

    pt4.c 

    #include <stdio.h>

    void pt(){

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

    }

    pt5.c 

    #include <stdio.h>

    void pt(){

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

    }

        然后,分别编译这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.... ");

            pt();

            printf("......end ");

            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!

  • 相关阅读:
    UVA 11488 Hyper Prefix Sets (字典树)
    UVALive 3295 Counting Triangles
    POJ 2752 Seek the Name, Seek the Fame (KMP)
    UVA 11584 Partitioning by Palindromes (字符串区间dp)
    UVA 11100 The Trip, 2007 (贪心)
    JXNU暑期选拔赛
    计蒜客---N的-2进制表示
    计蒜客---线段的总长
    计蒜客---最大质因数
    JustOj 2009: P1016 (dp)
  • 原文地址:https://www.cnblogs.com/wzheng/p/3487934.html
Copyright © 2011-2022 走看看