3

システムに 2 つのクラスとライブラリを追加し、そこparent.soからchild.so派生させています。

問題は、プログラムがロードchild.soされているときに、 から親の仮想関数の定義を見つけることができないことparent.soです。

何が起こるのですか、

nm -D child.so次のようなものを提供します(名前を変更しただけです)

U _ZN12PARENT15virtualFunctionEv


実行中のプログラムがクラッシュします

_handle = dlopen(filename, RTLD_NOW|RTLD_GLOBAL); //filename is child.so

エラーが発生しますLD_DEBUG = libs

symbol lookup error: undefined symbol: _ZN12PARENT15virtualFunctionEv (fatal)

説明できないのは、LD_DEBUG = symbolsGDB を使用しdlopenてみましたparent.so。しかし、libs ログからparent.soは既にロードされ、コードが実行されており、他のすべてのライブラリと同じパスにあります。

 ......
 27510:     symbol=_ZN12PARENT15virtualFunctionEv;  lookup in file=/lib/tls/libm.so.6
 27510:     symbol=_ZN12PARENT15virtualFunctionEv;  lookup in file=/lib/tls/libc.so.6
 27510:     symbol=_ZN12PARENT15virtualFunctionEv;  lookup in file=/lib/ld-linux.so.2
 27510:     child.so: error: symbol lookup error: undefined symbol: _ZN12PARENT15virtualFunctionEv(fatal)

プログラムまたはシステムは、シンボルの定義を探すライブラリをどのように管理していますか?

私は Linux を初めて使用します。作業の指示を誰か教えてもらえますか?

ありがとう。

編集

parent.soファイルを生成するために使用されるコマンドは

c++  -shared  -o parent.so parent.o

についても同様ですchild.so。ここにリンクするために不足している情報はありますか? 子には親のヘッダー ファイルのみが含まれているようです。

EDIT2

別のテストの後、呼び出し

_handle = dlopen("parent.so", RTLD_NOW|RTLD_GLOBAL);

クラッシュする行が問題を解決する前に、これはもともとロードされていなかったことを意味すると思いますparent.so。しかし、その原因についてはまだよくわかっていません。

4

3 に答える 3

4

libchild.soライブラリが の機能を使用していることをリンカーに伝える必要がありますlibparent.so。これは、子ライブラリを作成するときに行います。

g++ -shared -o libchild.so child_file1.o child_file2.o -Lparent_directory -lparent

順序が重要であることに注意してください。-lparent結局、オブジェクト ファイルを指定します。-Wlg++へのオプションを介してリンカーに追加のオプションを渡す必要がある場合もあります。

それはまだ十分ではないかもしれません。libparent.soを含むライブラリをLD_LIBRARY_PATH環境変数に追加する必要がある場合があります。

いくつかの落とし穴: これらのライブラリにlibプレフィックスを付けて名前を付けていない場合、リンカーを大いに混乱させます。-fPICどちらかでソースファイルをコンパイルしていない場合、または-fpic再配置可能なオブジェクトがありません。

補遺
他のライブラリに依存するライブラリには大きな潜在的な問題があります。子ライブラリ ソース ファイルをコンパイルするときに、親パッケージのバージョン 1.5 を使用するとします。ライブラリの依存関係の問題をすべて乗り越えることができます。libchild.soに依存することを指定しましたlibparent.so。あなたのものはうまくいきます。それは、親パッケージのバージョン 2.0 がリリースされるまでです。これで、使用されているすべての場所で問題が発生し、コードを 1 行も変更していません。

この問題を克服する方法は、子ライブラリをビルドするときに、結果の共有ライブラリが特に libparent.so` のバージョン 1.5 に依存することを指定することです。

これを行うには、オプションを介して g++/gcc からリンカーにオプションを渡す必要があり-Wlます。これらのリンカー オプションにスペースが必要な場合は、g++ へのコマンドでそれらをバックスラッシュでエスケープする-Wl,<linker_option>,<linker_option>,...必要があります。いくつかの重要なオプションは-rpath-sonameです。たとえば、-rpath=/path/to/lib,-soname=libparent.so.1.5.

よく注意してください: -soname=libparent.so.1.5libparent.so をビルドするときは、このオプションを使用する必要があります。これにより、システムは libchild.so (バージョン 1.0) が libparent.so (バージョン 1.5) に依存していることを示すことができます。また、libparent.so をビルドしません。libparent.so.1.5 をビルドします。libparent.so はどうですか? これは存在する必要がありますが、libparent.so の番号付きバージョン (できれば最新バージョン) へのシンボリック リンクである必要があります。

ここで、下位互換性のない親バージョン 2.0 がコンパイルされ、光沢のある新しい libparent.so.2.0 に組み込まれ、libparent.so がこの光沢のある新しいバージョンにシンボリックにリンクされているとします。不格好な古い libchild.so (バージョン 1.0) を使用するアプリケーションは、すべてを破壊する光沢のある新しい libparent.so の代わりに、不格好な古いバージョンの libparent.so を喜んで使用します。

于 2012-10-18T04:30:16.150 に答える
1

child.soにはparent.soが必要であることをリンカーに伝えていないようです。次のように使用してください。

g++ -shared -o libparent.so parent.o
g++ -shared -o libchild.so -lparent child.o
于 2012-10-18T01:33:53.297 に答える
-1

メイン プログラムをビルドするときは、それらのライブラリとリンクしていることをコンパイラに伝える必要があります。そうすれば、起動時にLinuxがそれらをロードします。

それらの名前を libparent.so および libchild.so に変更します。

次に、次のようにコンパイルします。

g++ <your files and flags> -L<folder where the .so's are> -lparent -lchild

編集:

おそらく、child.so の前に parent.so を読み込もうとすると、小さな変更になるでしょう。もう試しましたか?

于 2012-10-18T01:25:38.113 に答える