Получение неопределенной символьной ошибки при динамической загрузке разделяемой библиотеки - PullRequest
4 голосов
/ 23 марта 2012

Я получаю 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);
}

Но когда я загружаю библиотеку, просто комментируя приведенный выше код и экспортируя путь к библиотеке, все работает как charm.

Для динамического связывания я используюСледующая команда в командной строке.

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

Любая помощь будет оценена.

1 Ответ

9 голосов
/ 23 марта 2012

Скорее всего, вы видите Имя искажения в действии здесь.

Если вы хотите использовать dlopen() / dlsym() с общими библиотеками C ++, вам необходимо:

  1. объявляет функции, которые вы хотите просмотреть через dlsym(), как extern "C" { ... }, так что компилятор C ++ создает для них незащищенные имена.
    Это возможно только в том случае, если функциявы пытаетесь получить доступ к функции, не являющейся членом или статической, и не перегруженной (только одна подпись);C ++ не может создавать неупорядоченные имена в других ситуациях.
    Если кто-то запросил компилятор сделать это через extern "C" { ... }, и возможно создать неупорядоченное имя, оно дословно заканчивается в таблице символов ELF.Затем вы можете найти его, используя dlsym() точно так же, как и для любой функции C.
  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");, чтобы поиск был успешным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...