在动态加载共享库时获取未定义的符号错误 [英] Getting undefined symbol error while dynamic loading of shared library

查看:583
本文介绍了在动态加载共享库时获取未定义的符号错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

动态加载库时,我收到未定义的符号错误。
这是我的代码片段产生这个错误:

  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\\\
,dlerror());
exit(1);

}

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

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

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

dlclose(lib_handle);
}



但是,当我简单地通过注释上面的代码和导出库路径一切正常装载库like charm。



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



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



任何帮助将不胜感激。


解决方案

你很可能看到的名称重整的这里的行动。



如果您想使用C ++共享库使用 dlopen() / dlsym()


  1. 通过 dlsym()声明要查找的函数C $ C>的externC{...} 从而使C ++编译器创建的重整的的为他们的名字。结果
    这是如果只可能您尝试访问的函数是非成员或静态成员函数,并且不重载(只有单个签名);如果一个请求的编译器这样做通过的externCC ++不能创建在其他情况下重整的名字。结果
    {...}
    和可以创建一个未解析的名称,它在ELF符号表中逐字地结束。那么你可以看看它使用则dlsym()就像你会为所有的C函数。

  2. 找到了什么的 的名称。

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

      $ nm libstdc ++。 grep -v'^'| grep的意外
    0000000000000000牛逼__cxa_call_unexpected
    0000000000000000牛逼_ZN10__cxxabiv112__unexpectedEPFvvE
    0000000000000000牛逼_ZSt10unexpectedv
    0000000000000000牛逼_ZSt14set_unexpectedPFvvE
    0000000000000000ð_ZN10__cxxabiv120__unexpected_handlerE

    这些是错误的名称,C ++编译器实际放入ELF对象。如果您使用 -C 选项请求 nm 解构您将获得:

      $ nm -C libstdc ++。 grep -v'^'|用grep意想不到的
    0000000000000000牛逼__cxa_call_unexpected
    0000000000000000牛逼__cxxabiv1 :: __意外(无效(*)())
    0000000000000000牛逼的std ::意想不到的()
    0000000000000000牛逼的std :: set_unexpected( void(*)())
    0000000000000000 D __cxxabiv1 :: __ unexpected_handler

    lib中,如果你想为函数指针的std ::意想不到的()从中,你有权要求则dlsym(HDL ,_ZN10__cxxabiv112__unexpectedEPFvvE); 以使查找成功。


    I am getting undefined symbol error while loading library dynamically. 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.

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

    1. declare the functions you want to lookup through dlsym() as extern "C" { ... } so that the C++ compiler creates unmangled names 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 mangled name of the function is, and use that in your dlsym() call.

    The latter you can do via the nm utility. 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. If you use the -C option to request nm to demangle the names for you, you get:

    $ 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.

    这篇关于在动态加载共享库时获取未定义的符号错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆