编译时已经链接,但运行程序时找不到共享对象库

8

更新:问题已解决。该库是为Armv7a CPU设计的,但它是“软浮点”而不是“硬浮点”。似乎我的机器与SF不兼容,而是HF兼容。

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

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

IT报告指出有很多未定义的引用,显然是因为我在编译时没有包含libMyLib.so库文件。所以编译器不知道他需要编译哪些程序。当我这样编译程序:

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

它没有报告任何错误,创建了文件“run”。请注意,libMyLib.so已经在/usr/local/lib中,而且在编译时似乎已经链接了,因为现在已经定义了引用,并且创建了“run”文件。但是当我运行该文件时,会出现以下情况:

$ ./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
...

我真的不知道为什么这种情况仍然会发生。有人可以帮助我吗?

2个回答

8

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

然而,在运行时,程序加载器默认在以下位置搜索已链接的库:

  • /lib/usr/lib和在ldconfig缓存中缓存名称和位置的库/etc/ld.so.cache之间进行搜索。
  • 在当前shell中环境变量LD_LIBRARY_PATH的值所列出的目录中。

只有在运行ldconfig时,ldconfig缓存才会更新。参见man ldconfig

加载器无法在运行时找到libMyLib.so,因为您自从将该库放置在/usr/local/lib以来,还没有运行过ldconfig,也没有在尝试运行程序的同一shell中正确地添加/usr/local/libLD_LIBRARY_PATH中。

要求特殊设置LD_LIBRARY_PATH以使程序运行是不方便且不可取的。

要使加载器找到您的库,请以root身份运行ldconfig。只要/usr/local/lib/etc/ld.so.conf或被/etc/ld.so.conf包含的文件中列出,这将成功。如果没有列出,则可以通过以root身份运行ldconfig /usr/local/lib来显式缓存/usr/local/lib中的共享库。


这解决了我的问题,但是我该如何配置cmake将我的软件安装在/lib而不是/usr/local/lib中。以root作为前缀似乎很荒谬。我不想在我的根目录下有不必要的文件夹。 - Tarun Maganti

5

首先检查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 - skr
感谢您的支持,但这也无法解决问题。这可能是由于.so库中缺少依赖项引起的吗? - Karkan
您能否尝试一下 strace ldd run 呢? - skr
strace -f ldd run首先尝试打开实际的libMyLib.so库:[pid 2747] open("/usr/lib/libMyLib.so", O_RDONLY|O_CLOEXEC) = 3。经过几次read()和seeks()调用后,它调用close(3)。然后它开始尝试再次打开libMyLib.so,但是从许多不同的位置[pid 2747] open("/lib/arm-linux-gnueabihf/tls/v7l/neon/vfp/libMyLib.so", O_RDONLY|O_CLOEXEC)=-1 ENOENT (没有此文件或目录)。它以类似于暴力破解的方式尝试了几个路径(以寻找正确的位置)。 - Karkan
抱歉给您带来不便。我也联系了libMyLib.so的创建者。显然他们一开始给了我错误的库文件。虽然该库文件确实是Arm v7,但它并不是硬浮点。他们给了我一个新的库文件,现在一切都正常了。 - Karkan
显示剩余8条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接