我写了下一个程序:

#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


运行该程序时,我看不到任何消息。为什么?

感谢您的关注。

最佳答案

您的过程有问题,因为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;
}

10-08 13:00