【问题标题】:shared object library not found when running program, but it's linked during compiling运行程序时未找到共享库,但在编译时已链接
【发布时间】:2018-01-07 05:23:18
【问题描述】:

更新:问题已解决。该库是为 Armv7a CPU 制作的,但它是“软浮动”而不是“硬浮动”。看来我的机器是 HF 而不是 SF 兼容

我的程序依赖于一个名为 libMyLib.so 的外部构建 .so 库。当我像这样编译程序时:

$ g++ -std=c++11 main.cpp -o run -pthread

它报告有很多未定义的引用,显然是因为我在编译时没有包含 libMyLib.so。所以编译器知道他需要什么来编译程序。当我像这样编译程序时:

$ g++ -std=c++11 main.cpp -o run -pthread -lMyLib

它不报告任何错误并创建文件“运行”。请注意,libMyLib.so 已经在 /usr/local/lib 中,并且在编译时看起来像已链接,因为现在定义了引用并创建了“运行”文件。但是当我运行文件时,会发生这种情况:

$ ./run
    ./run: error while loading shared libraries: libMyLib.so: cannot open shared object file: No such file or directory

我检查了 ldd,它告诉我:

$ ldd run
    ...
    libMyLib.so => not found
    ...

所以 ldd 在执行时找不到库,但在编译时会找到它。我对 Linux 和链接库还很陌生,所以我不知道该怎么做。

另外,在 .so 文件上运行 ldd 会返回:

$ ldd /usr/local/lib/libMyLib.so
    not a dynamic executable

我已经检查过在错误平台上运行 .so 文件时可能会出现此消息。但我已经检查过,该库是为 arm 编译的(我在树莓派上运行 -> arm):

$  objdump -f /usr/local/lib/libMyLib.so | grep ^architecture
    architecture: arm, flags 0x00000150:

我还更新了链接器:

$ sudo ldconfig -v
...
/usr/local/lib:
    libwiringPi.so -> libwiringPi.so.2.44
    libwiringPiDev.so -> libwiringPiDev.so.2.44
    libMyLib.so -> libMyLib.so.1
...

我真的不知道为什么这仍然会发生。谁能帮帮我?

【问题讨论】:

    标签: c++ linux linker g++


    【解决方案1】:

    /usr/local/lib 是链接器默认搜索的目录之一 对于使用 -l 选项指定的库,因此您的链接成功。

    然而,在运行时,程序加载器默认搜索链接的 图书馆在:-

    • /lib/usr/lib 以及名称和位置已缓存在 ldconfig 缓存中的库中,/etc/ld.so.cache
    • 环境变量LD_LIBRARY_PATH的值中列出的目录, 在当前 shell 中。

    ldconfig 缓存仅在 ldconfig 运行时更新。见man ldconfig

    加载器在运行时找不到libMyLib.so,因为你没有 运行ldconfig,因为您将该库放在/usr/local/lib 和 您也没有正确地将/usr/local/lib 添加到LD_LIBRARY_PATH 在您尝试运行程序的同一 shell 中。

    要求对 LD_LIBRARY_PATH 使程序能够运行。

    要使加载器能够找到您的库,请以 root 身份运行 ldconfig。这 如果/usr/local/lib/etc/ld.so.conf 中列出,则将成功, 或在/etc/ld.so.conf 包含的文件之一中。如果不是,那么 您可以通过运行显式缓存来自/usr/local/lib 的共享库 ldconfig /usr/local/lib,以 root 身份。

    【讨论】:

    • 这解决了我的问题,但是如何配置 cmake 以将我的软件安装在 /lib 而不是 /usr/local/lib。将 root 作为前缀似乎很荒谬。我不希望根文件夹中有不必要的文件夹。
    【解决方案2】:

    首先检查 LD_LIBRARY_PATH 变量是否包含库目录的路径

    $ echo $LD_LIBRARY_PATH
    

    如果不存在则更新库路径。

    $ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/path/to/library
    

    使用 strace 进行调试。

    strace -f ./run
    

    【讨论】:

    • LD_LIBRARY_PATH=/usr/local/lib/:$LD_LIBRARY_PATH ./run 试试这个
    • 感谢您的支持,但这也无济于事。会不会因为 .so 库中缺少依赖项而发生这种情况?
    • 您可以尝试2个选项。 1 strace 命令和 2. objdump -f /usr/local/lib/libMyLib.so | grep NEEDED 并检查依赖库是否存在。
    • 已经签出选项 2。选项 1 显示如下输出: open("/usr/lib/tls/v7l/neon/vfp/libMyLib.so", O_RDONLY|O_CLOEXEC) = -1 ENOENT (没有这样的文件或目录)\n stat64("/usr/lib/tls/v7l/neon/vfp", 0x7eb967b8) = -1 ENOENT (没有这样的文件或目录) ..... 它有几个路径组合并检查多个路径,例如 /usr/lib、usr/local/lib、...我现在正在 google 上检查结果
    • 两个问题open("/path/to/library/libMyLib.so") 这个在strace 中出现吗,libMyLib.so 的权限和其他库一样。
    猜你喜欢
    • 2014-04-29
    • 2011-06-12
    • 1970-01-01
    • 2018-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    相关资源
    最近更新 更多