dlsym()/dlopen() 的用法
Posted
技术标签:
【中文标题】dlsym()/dlopen() 的用法【英文标题】:Usage of dlsym()/dlopen() 【发布时间】:2014-05-14 11:59:10 【问题描述】:我写了下一个程序:
#include <iostream>
#include <dlfcn.h>
int main(int argc, char** argv)
typedef void* (*fptr)();
fptr func;
void *handle = dlopen(0, RTLD_NOW);
std::cout << dlerror() << std::endl;
*(void **)(&func) = dlsym(handle, "__libc_start_main");
std::cout << dlerror() << std::endl;
std::cout << handle << " " << func << "\n";
dlclose(handle);
return 0;
并尝试用下一种方式编译:
g++ -rdynamic main.cpp -ldl -o test
当我运行这个程序时,我没有看到任何消息。为什么?
感谢您的关注。
【问题讨论】:
【参考方案1】:您的进程出错了,因为 dlerror()
仅在 error 条件下调用才有效,而您在调用之前从未验证过该情况实际发生过。
来自Linux docs:
函数
dlerror()
返回一个人类可读的字符串,描述 从dlopen()
、dlsym()
或dlclose()
发生的最新错误 自上次致电dlerror()
以来。 如果没有错误则返回 NULL 自初始化或自上次调用以来发生。
换句话说,你的dlopen
成功了,所以从dlerror()
返回NULL。然后将该 NULL 作为char *
发送到std::cout
和kerboom。
底线:在调用 dlerror()
之前检查您的错误情况。试试这个:
#include <iostream>
#include <dlfcn.h>
int main(int argc, char** argv)
typedef void* (*fptr)();
fptr func;
void *handle = dlopen(0, RTLD_NOW);
if (handle == nullptr)
std::cout << dlerror() << std::endl;
exit(EXIT_FAILURE);
func = (fptr)dlsym(handle, "__libc_start_main");
if (!func)
std::cout << dlerror() << std::endl;
exit(EXIT_FAILURE);
std::cout << handle << " " << func << "\n";
dlclose(handle);
return 0;
【讨论】:
【参考方案2】:这是(可能)未定义的行为:
std::cout << dlerror() << std::endl;
...除非dlerror
实际上是非空的(它可能不是)。应该是:
char* error = dlerror();
if (error != 0)
std::cout << error << std::endl;
...或:
void *handle = dlopen(0, RTLD_NOW);
if (handle == 0)
std::cout << dlerror() << std::endl;
此外,如果dlerror
不为空(或handle
为空),您可能应该中止,因为在空handle
上调用dlsym
也是未定义的行为。
见Why does std::cout output disappear completely after NULL is sent to it。
【讨论】:
谢谢你。这是如何处理成员函数的最后一个问题。 typedef void (A::*fptr)();而不是尝试类似 func = (fptr)dlsym(handle, "test");比这是编译错误,因为他不知道如何将 void 转换为 fptr。你能帮我解决这个问题吗?以上是关于dlsym()/dlopen() 的用法的主要内容,如果未能解决你的问题,请参考以下文章
用dlopen和dlsym得到的符号 在dlclose后还能继续使用么
C:尽管添加了 `-ldl` 标志,但未定义对 `dlopen`/`dlsym` 的引用