Getting undefined symbolic error while dynamically loading shared library

I get an undefined symbol error when dynamically loading a library. Here is my piece of code 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 the library by simply commenting on the code above and exporting the library path, everything works like a charm.

For dynamic linking, I use the following command on the command line.

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

Any help would be appreciated.

+4
c ++ linux shared-libraries dynamic-loading
source share
1 answer

You will most likely see the action here in Mangling.

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

  • declare the functions you want to view through dlsym() as extern "C" { ... } so that the C ++ compiler creates unconnected names for them.
    This is only possible if the function you are trying to get is a non-member or static member function and is not overloaded (only one signature); C ++ cannot create unrelated names in other situations.
    If someone asked the compiler to do this via extern "C" { ... } , and you can create an intact name, it ends verbatim in the ELF character table. You can then view it with dlsym() in the same way as with any C function.
  • Find out what a malformed function name is and use this in your dlsym() call.

You can do the latter with 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 garbled names that the C ++ compiler really puts in an ELF object. If you use the -C option to request nm to expand the names for you, you will 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 

This means that for this library, if you want to get a pointer to std::unexpected() , you need to query dlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE"); to make the search successful.

+9
source share

All Articles