c++ - 动态加载共享库时出现 undefined symbol 错误

标签 c++ linux shared-libraries dynamic-loading

动态加载库时出现undefined symbol 错误。 这是我生成此错误的代码片段:

int main ()
{

    void *lib_handle = NULL;

    MyClass* (*create)();
    void (*destroy)(MyClass*);
    char *error;


    lib_handle = dlopen ("./libshared.so", RTLD_LAZY);

    if (lib_handle == NULL) 
    {
        fprintf(stderr, "%s\n", dlerror());
        exit(1);

    } 

    create = (MyClass* (*)()) dlsym(lib_handle, "create_object");
    if ((error = dlerror()) != NULL)  
   {
      fprintf(stderr, "%s\n", error);
      exit(1);
   }

    destroy = (void (*)(MyClass*)) dlsym(lib_handle, "destroy_object");

    MyClass *myClass = (MyClass*) create;
    destroy(myClass);   

    dlclose(lib_handle);
}

但是当我简单地通过评论上面的代码和导出库路径来加载库时,一切都像魅力一样。

对于动态链接,我在命令提示符下使用以下命令。

g++ -Wl,--export-dynamic shared_user.cpp -ldl

如有任何帮助,我们将不胜感激。

最佳答案

您很可能会在这里看到Name Mangling

如果您想将 dlopen()/dlsym() 与 C++ 共享库一起使用,您需要:

  1. 将您要通过 dlsym() 查找的函数声明为 extern "C"{ ... } 以便 C++ 编译器创建unmangled 他们的名字。
    这仅在您尝试访问的函数是非成员函数或静态成员函数且未重载(仅单个签名)时才有可能; C++ 无法在其他情况下创建未损坏的名称。
    如果有人通过 extern "C"{ ... } 请求编译器这样做,并且有可能创建一个未损坏的名称,它最终会逐字地出现在 ELF 符号表中。然后,您可以像查找任何 C 函数一样使用 dlsym() 查找它。
  2. 找出函数的损坏名称是什么,并在您的dlsym() 调用中使用它。

后者可以通过 nm 实用程序完成。例如:

$ nm libstdc++.a | grep -v '^ ' | grep unexpected
0000000000000000 T __cxa_call_unexpected
0000000000000000 T _ZN10__cxxabiv112__unexpectedEPFvvE
0000000000000000 T _ZSt10unexpectedv
0000000000000000 T _ZSt14set_unexpectedPFvvE
0000000000000000 D _ZN10__cxxabiv120__unexpected_handlerE

这些是错位 名称,C++ 编译器实际上已放入 ELF 对象中。如果您使用 -C 选项请求 nm 为您demangle 名称,您将获得:

$ nm -C libstdc++.a | grep -v '^ ' | grep unexpected
0000000000000000 T __cxa_call_unexpected
0000000000000000 T __cxxabiv1::__unexpected(void (*)())
0000000000000000 T std::unexpected()
0000000000000000 T std::set_unexpected(void (*)())
0000000000000000 D __cxxabiv1::__unexpected_handler

这意味着对于这个库,如果你想从中获取指向 std::unexpected() 的函数指针,你必须请求 dlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE"); 使查找成功。

关于c++ - 动态加载共享库时出现 undefined symbol 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9837009/

相关文章:

c++ - 堆栈上的竞争条件

c++ - glScissor() 在另一个 glScissor() 中调用

linux - 从剥离的 ELF 二进制文件估计编译器(GCC 或 LLVM-clang)版本

mysql - 将 MySQL "SELECT"查询传递给 shell 变量

c++ - 在库中使用 Qt5

使用第三方库的 C++ 链接错误

c++ - boost::circular_buffer 不支持 move 语义是否有任何技术/概念原因?

c++ - 设置 'deep' 配置选项的最佳方法是什么?

linux - Bash 脚本,不包括值

visual-c++ - Visual Studio : ignore undefined references in shared libraries