【问题标题】:Usage of dlsym()/dlopen()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

当我运行这个程序时,我没有看到任何消息。为什么?

感谢您的关注。

【问题讨论】:

    标签: c++ posix symbols


    【解决方案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。你能帮我解决这个问题吗?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-20
      • 1970-01-01
      • 1970-01-01
      • 2010-11-07
      • 1970-01-01
      • 2012-06-01
      相关资源
      最近更新 更多