dlopen()返回0

时间:2019-06-10 20:14:44

标签: c++ linux g++ dlopen

在我的目录中,我有两个文件。一个是foo.cpp,另一个是bar.so。在foo.cpp中,我试图加载库bar.so

#include <dlfcn.h>
#include <iostream>

int main()
{
    void* handle = dlopen("bar.so", RTLD_NOW | RTLD_GLOBAL);
    std::cout << handle << std::endl;
    return 0;
}

然后在同一目录中,使用以下命令从命令行编译代码:

g++ foo.cpp -ldl -o test

但是,在执行test时,将打印出0,并根据dlopen的文档进行显示:

  

如果dlopen()由于任何原因失败,则返回NULL

当库文件与CPP文件位于同一目录时,为什么为什么返回NULL?


更新:

我现在已将dlopen()添加到我的CPP文件中,并输出:

bar.so: cannot open shared object file: No such file or directory

但是我不明白... bar.sofoo.cpp在同一目录中,可执行文件在此目录中构建,并且在运行可执行文件时在同一目录中

因此,我尝试为bar.so使用绝对路径,但随后收到一个新错误:

invalid ELF header

快速浏览Google之后,我认为这可能是由于我安装了Ubuntu。我实际上使用的是MacBook,并且已经安装了Ubuntu的本机副本(不是虚拟机)。看来这是造成问题的原因,但我不知道如何解决。也许该库文件仅在MacBook Ubuntu上不起作用。

1 个答案:

答案 0 :(得分:4)

  

当库文件与CPP文件位于同一目录时,为什么为什么返回NULL?

.cpp文件的位置与此处无关。

可执行文件的位置或LD_LIBRRY_PATH的设置是在运行时用来解析的。

无论如何,不​​建议使用LD_LIBRRY_PATH长期解决方案。最简单的方法是使用"./bar.so"而不是"bar.so",以便dlopen()首先在当前目录中查找。但是当前目录可能与可执行文件的存储目录不同。在这种情况下,dlopen()仍然会失败。

另一种解决方案是在编译可执行文件(在这种情况下为-Wl,-rpath='$ORIGIN'时,将foo.cpp添加到编译标志中,并像以前一样传递"bar.so"。使用$ORIGIN作为rpath时,当前目录是什么都没有关系。 dlopen()将始终始终在可执行文件的目录中查找。但是请注意,这将导致首先在当前目录中查找所有库,而不仅仅是您尝试dlopen()的库。可能是您想要的,也可能不是。

所以最好的解决方案是在运行时获取可执行文件所在目录的路径,并将其用作bar.so的路径。这是系统特定的。在Linux上,请参见:Get path of executable