6

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

しかし、上記のコードにコメントを付けてライブラリパスをエクスポートするだけでライブラリをロードすると、すべてが魅力的に機能します。

動的リンクの場合、コマンド プロンプトで次のコマンドを使用しています。

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

どんな助けでも大歓迎です。

4

1 に答える 1

12

ここでは、 NameManglingが実際に動作しているのを目にする可能性が非常に高くなります。

dlopen()/dlsym()をC++共有ライブラリで使用する場合は、次のいずれかを行う必要があります。

  1. ルックアップする関数を宣言して、C++コンパイラーがそれらの関数にdlsym()マングルextern "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すると、次のようになります。

$ 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

つまり、このlibの場合、そこから関数ポインターを取得する場合は、ルックアップを成功させるようstd::unexpected()に要求する必要があります。dlsym(hdl, "_ZN10__cxxabiv112__unexpectedEPFvvE");

于 2012-03-23T10:55:28.157 に答える