Linux 动态加载共享库时出现未定义符号错误

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/9837009/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 05:21:44  来源:igfitidea点击:

Getting undefined symbol error while dynamic loading of shared library

c++linuxshared-librariesdynamic-loading

提问by Yuvi

I am getting undefined symbolerror while loading library dynamically. Here is my code snippet that generates this error :

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);
}

But when I load library simply by commenting above code and exporting library path everything works like charm.

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

For dynamic linking I am using the following command on command prompt.

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

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

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

Any help would be appreciated.

任何帮助,将不胜感激。

回答by FrankH.

You're very likely seeing Name Manglingin action here.

您很可能会在这里看到Name Mangling 的运行情况。

If you want to use dlopen()/ dlsym()with C++ shared libraries, you either need to:

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

  1. declare the functions you want to lookup through dlsym()as extern "C" { ... }so that the C++ compiler creates unmanglednames for them.
    This is only possible if the function you try to access is a non-member or static member function, and not overloaded (only a single signature); C++ can't create unmangled names in other situations.
    If one requested the compiler to do so via extern "C" { ... }and it's possible to create an unmangled name, it ends up verbatim in the ELF symbol table. You can then look it up using dlsym()exactly like you would for any C function.
  2. Find out what the mangledname of the function is, and use that in your dlsym()call.
  1. 声明要查找的函数dlsym()extern "C" { ... }以便 C++ 编译器为它们创建未混淆的名称。
    这仅在您尝试访问的函数是非成员或静态成员函数且未重载(只有单个签名)时才有可能;在其他情况下,C++ 无法创建未混淆的名称。
    如果要求编译器这样做,extern "C" { ... }并且可以创建一个未混淆的名称,则它最终会在 ELF 符号表中逐字逐句。然后,您可以dlsym()像查找任何 C 函数一样使用它来查找它。
  2. 找出函数的损坏名称,并在您的dlsym()调用中使用它。

The latter you can do via the nmutility. For example:

后者您可以通过该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

These are the manglednames, what the C++ compiler has actually put into the ELF object. If you use the -Coption to request nmto demanglethe names for you, you get:

这些都是缺胳膊少腿的名字,有什么C ++编译器实际上已经投入了ELF对象。如果您使用的-C选项要求nm,以还原函数你的名字,你会得到:

$ 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

That means for this lib, if you'd want to get the function pointer to std::unexpected()from it, you'd have to request dlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE");to make the lookup succeed.

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