dlsym()/ dlopen()的用法

时间:2014-05-14 11:59:10

标签: c++ posix symbols

我写了下一个程序:

#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的关注。

2 个答案:

答案 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