web-dev-qa-db-ja.com

非常に奇妙なリンカーの動作

これは奇妙なことです。libmへの参照を削除することで、以下のエラーを取得できたからです。

gcc -o example example.o -Wl -L/home/kensey/cdev/lib -L/usr/lib/x86_64-linux-gnu   -lmysqlclient -lpthread -lz -L/usr/lib/x86_64-linux-gnu -lm -lrt -ldl -lcdev -L/home/kensey/www.tools/gplot-lib -lgplot -L/home/kensey/www.tools/Gd1_3ret -lgd -lxml2 -lcurl
/usr/bin/ld: /home/kensey/www.tools/gplot-lib/libgplot.a(set.o): undefined reference to symbol 'floor@@GLIBC_2.2.5'
/usr/bin/ld: note: 'floor@@GLIBC_2.2.5' is defined in DSO /usr/lib/x86_64-linux-gnu/libm.so so try adding it to the linker command line
/usr/lib/x86_64-linux-gnu/libm.so: could not read symbols: Invalid operation
collect2: ld returned 1 exit status

したがって、コマンドの-lm部分を削除しても、エラーは発生しません。ただし、必要なライブラリへの参照を削除するとこれが修正される理由について誰かが知っているのだろうか。リンカはどのライブラリを調べるべきかをどのようにして知るのですか?また、ビルドされた実行可能ファイルを照会し、「どのライブラリを「フロア」への参照を解決しましたか」と言う方法はありますか?明らかに、私が理解していないこと、そして私を悩ます何かが起こっています...

45
Don Wool

何が起こっているのかの説明は非常に簡単です。

  1. libgplot.alibm.soに依存していますが、リンク行の-lm-lgplotの順序が間違っています。リンク行のライブラリの順序doesmatter 。一般に、システムライブラリ(-lpthread-lm-lrt-ldl)はfollowである必要がありますリンク行のその他すべて。

  2. リンク行から-lmを削除しても、libm.so.6は、リンク行に後で表示される他のライブラリによってリンクに引き込まれます(libgdlibxml2またはlibcurl)そのライブラリはlibm.so.6に依存しているため。しかし、今ではlibm.so.6はリンク行の正しい場所にあるため、すべてが機能します。

リンクコマンドの最後に-lmを付けて、最後のライブラリとしてリストすると、エラーは発生しません。

上記の説明を確認します。

83

export LDFLAGS="$LDFLAGS -lm"で同じ問題を解決しました

8
dmnc

おそらく、ライブラリ検索パス(/ usr/local/lib /または/ usr/lib /など)に64ビットlibmが含まれていないため、lフラグで指定した場合、gccはそれを見つけることができません。ディレクトリのみを指定すると、正しいディレクトリを見つけることができるように見えます。だからあなたは試すことができます:

LD_LIBRARY_PATH=/usr/lib/x86_64-linux-gnu

そして、-lm

6
perreal

わかりにくい。コマンドラインにカスタムライブラリディレクトリがあるため、-lmが互換性のない代替バージョンにリンクしていると考えられます。 -lmがなければ、リンクするライブラリの1つで必要になるため、リンカーは別のバージョンを取り込むことができます。

straceの両方の呼び出しを確認し、両方のケースでlibm.soがどこから来ているかを確認します。

ところで、-Wlスイッチは何もしないようで、-L/usr/lib/x86_64-linux-gnuが2回言及されています。

3

回答のリストに追加するだけで、 http://fedoraproject.org/wiki/UnderstandingDSOLinkChange これは有益です。上記の質問には関係ありませんが、説明はエラーメッセージ/usr/bin/ld: note: 'some_reference' is defined in DSO some.so so try adding it to the linker command line

2
venkrao

1つの説明couldは次のとおりです。

Libmの外部で定義された弱リンク関数fooが、libmの内部で定義されたfooの強リンクバージョンに置き換えられている可能性があります。未定義関数を呼び出すのはこの強リンクバージョンです。

これは、ライブラリを追加すると未定義関数エラーが発生する原因を説明します。

1
Andrew Tomazos

同様の問題が発生しました。 gccの過去には、ライブラリの順序は重要ではありませんでした(少なくとも私が作業した場合は関係ありません)。 こちらの質問 誰かが、動作が4.4と4.5の間で変更されたように見えることに気付きました。

私の場合、次のリンクを実行してエラーメッセージを削除しました。

 g++ -Wl,--copy-dt-needed-entries [options] [libraries] [object files] -o executable-file
1
Andre Holzner