c++ - dlopen() 返回 0
问题描述
在我的目录中,我有两个文件。一个是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.so
并且foo.cpp
在同一个目录中,可执行文件是在同一个目录中构建的,当我运行可执行文件时我在同一个目录中。
因此,我尝试使用绝对路径bar.so
,但随后收到一个新错误:
invalid ELF header
在快速谷歌之后,我认为这可能是由于我的 Ubuntu 安装。我实际上使用的是 MacBook,并且安装了 Ubuntu 的本机副本(不是虚拟机)。似乎这是导致问题的原因,但我不知道如何解决。也许这个库文件不能在 MacBook Ubuntu 上运行。
解决方案
那么,当库文件与 CPP 文件位于同一目录时,为什么返回 NULL 呢?
文件的位置在.cpp
这里无关紧要。
可执行文件的位置,分别LD_LIBRRY_PATH
是用于在运行时解析的设置。
无论如何,LD_LIBRRY_PATH
不是推荐的长期解决方案。最简单的一个是使用"./bar.so"
而不是"bar.so"
这样,dlopen()
它首先在当前目录中查找。但是当前目录可能与存储可执行文件的目录不同。在这种情况下,dlopen()
仍然会失败。
另一种解决方案是在编译可执行文件时(在这种情况下)添加-Wl,-rpath='$ORIGIN'
到编译标志并像以前一样传递。当用作 rpath 时,当前目录是什么并不重要。dlopen() 将始终首先查看可执行文件的目录。但请注意,这将导致首先在当前目录中查找所有库,而不仅仅是您尝试 dlopen() 的那些库。它可能是也可能不是你想要的。foo.cpp
"bar.so"
$ORIGIN
所以最好的解决方案是在运行时获取可执行文件所在目录的路径,并将其用作bar.so
. 这是系统特定的。在 Linux 上,请参阅:获取可执行文件的路径
推荐阅读
- ajax - 为什么 Ajax 在 laravel 上得到 500 内部错误
- batch-file - 如何循环浏览 Windows 服务并将它们与文本文件进行批量比较
- java - 有没有办法让我在java中的单一方法中加密和解密给定密钥的消息?
- javascript - 如何链接 JavaScript 文件以使用其他文件中的数组
- swiftui - SwiftUI 如何检测视图何时具有焦点?
- linux - 使用 Locust 对同时从 CSV 加载的多个 URL 运行负载测试
- arrays - 二分查找排序,超时
- node.js - AWS Lambda 节点JS 12
- r - 如何解决负二项式拟合(glm.nb)错误?
- python - 当 unittest.patch 只接受一个时,如何将两个位置参数传递给它?