我写了下一个程序:
#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
当我运行此程序时,我看不到任何消息。为什么呢?
感谢U的关注。
答案 0 :(得分:5)
您的流程存在错误,因为dlerror()
仅对在错误条件下调用有效,您在调用之前从未验证过该条件。
来自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;
}
答案 1 :(得分: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
为空),您可能应该中止,因为在dlsym
上调用handle
也是未定义的行为。
请参阅Why does std::cout output disappear completely after NULL is sent to it。