简体   繁体   English

动态加载共享库时获取未定义的符号错误

[英]Getting undefined symbol error while dynamic loading of shared library

I am getting undefined symbol error while loading library dynamically. 我动态加载库时遇到undefined symbol错误。 Here is my code snippet that generates this error : 这是我生成此错误的代码段:

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

Any help would be appreciated. 任何帮助,将不胜感激。

You're very likely seeing Name Mangling in 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 unmangled names for them. 通过dlsym()将要查找的函数声明为extern "C" { ... }以便C ++编译器为它们创建未编码的名称。
    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. 在其他情况下,C ++无法创建未编码的名称。
    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. 如果有人要求编译器通过extern "C" { ... }来执行此操作,并且可以创建一个未编码的名称,则它会在ELF符号表中逐字结束。 You can then look it up using dlsym() exactly like you would for any C function. 然后你可以使用dlsym()查找它,就像你对任何C函数一样。
  2. Find out what the mangled name of the function is, and use that in your dlsym() call. 找出函数的错位名称,并在dlsym()调用中使用它。

The latter you can do via the nm utility. 后者可以通过nm实用程序完成。 For example: 例如:

$ 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 mangled names, what the C++ compiler has actually put into the ELF object. 这些是受损的名称,C ++编译器实际放入ELF对象的名称。 If you use the -C option to request nm to demangle the names for you, you get: 如果您使用-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"); 这意味着对于这个lib,如果你想从它获取std::unexpected()的函数指针,你必须请求dlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE"); to make the lookup succeed. 使查找成功。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM