gccの'-l'オプションの順番はなぜ重要なのですか?重複] [重複] [重複
質問
を使用するプログラムをコンパイルしようとしています。 udis86 ライブラリを使用するプログラムをコンパイルしようとしています。実際に使っているのは ユーザーマニュアル にあるサンプルプログラムを使用しています。しかし、コンパイル中にエラーが発生します。私が得たエラーは、次のとおりです。
example.c:(.text+0x7): undefined reference to 'ud_init'
example.c:(.text+0x7): undefined reference to 'ud_set_input_file'
.
.
example.c:(.text+0x7): undefined reference to 'ud_insn_asm'
私が使っているコマンドは
$ gcc -ludis86 example.c -o example
のように、ユーザーマニュアルの指示に従い
明らかにリンカはlibudisライブラリをリンクすることができません。しかし、私のコマンドを変更すると
$ gcc example.c -ludis86 -o example
これは動作し始めます。だから、最初のコマンドの何が問題なのか、誰か説明してください。
どのように解決するのですか?
GNUリンカが使用するリンクアルゴリズムがそのように動作するからです(少なくとも静的ライブラリのリンクに関しては)。リンカーはシングルパスリンカーであり、一度見たライブラリを再訪問することはありません。
ライブラリはオブジェクトファイルのコレクション(アーカイブ)です。ライブラリを追加するときは
-l
オプションを使ってライブラリを追加した場合、リンカは無条件に
すべて
オブジェクトファイルを取り込みます。オブジェクトファイルを取り込みます。
現在必要とされている
つまり、現在未解決の(保留の)シンボルを解決するファイルです。その後、リンカーはそのライブラリのことを完全に忘れます。
保留中のシンボルのリストは、リンカーが入力オブジェクトファイルを左から右へ次々に処理するときに、リンカーによって継続的に維持されます。各オブジェクト ファイルを処理する際に、いくつかのシンボルは解決されてリストから削除され、他の新しく発見された未解決のシンボルはリストに追加されます。
ですから、もしあなたがあるライブラリを
-l
を使用した場合、リンカーはそのライブラリを使用して現在保留中のシンボルを可能な限り解決し、その後そのライブラリのことは完全に忘れます。もし
後に
が突然、そのライブラリから追加のオブジェクト ファイルが必要であることを発見しても、リンカは追加のオブジェクト ファイルを取得するためにそのライブラリに "return" することはありません。それはすでに遅すぎるのです。
この理由から、常に
-l
オプション
遅く
を使うことで、リンカがその
-l
に到達するまでに、どのオブジェクトファイルが必要でどれが必要でないかを確実に判断できるようにします。このように
-l
オプションをリンカへの最初のパラメータとして置くことは、 一般に全く意味がありません:最初の段階では、保留中のシンボルのリストは空です (より正確には、単一のシンボル
main
で構成される)、つまりリンカがライブラリから何も取得しないことを意味します。
あなたの場合、オブジェクトファイル
example.o
にはシンボル
ud_init
,
ud_set_input_file
などです。リンカはそのオブジェクトファイルを最初に受け取るはずです。リンカはこれらのシンボルを保留中のシンボルリストに追加します。その後で
-l
オプションを使ってライブラリを追加します。
-ludis86
. リンカはあなたのライブラリを検索し、保留中のシンボルを解決するものをすべて取得します。
もしあなたが
-ludis86
オプションを最初に置くと、リンカーは効果的に
を無視します。
が必要であることを知らないので、リンカは事実上あなたのライブラリを無視します。
ud_init
,
ud_set_input_file
などです。その後、処理する際に
example.o
を処理するときに、これらのシンボルを発見し、保留中のシンボルリストに追加します。しかし、これらのシンボルは最後まで未解決のままであり、なぜなら
-ludis86
はすでに処理された(そして事実上無視された)ので、 これらのシンボルは最後まで未解決のままです。
時には、2つ(またはそれ以上)のライブラリが循環的にお互いを参照している場合、1つのライブラリに対して
-l
オプションを同じライブラリで2回使用することで、リンカがそのライブラリから必要なオブジェクトファイルを取得する機会を2回与えることができます。
関連
-
[解決済み] LD_LIBRARY_PATH と LIBRARY_PATH の比較
-
[解決済み] SQLiteのINSERT/per-secondのパフォーマンスを向上させる
-
[解決済み] なぜGCCはa*a*a*a*aを(a*a*a)*(a*a*a)に最適化しないのでしょうか?
-
[解決済み] C言語では「?」演算子は何をするのですか?
-
[解決済み] 配列の場合、なぜ a[5] == 5[a] になるのでしょうか?
-
[解決済み] Cプリプロセッサはなぜ "linux "という単語を定数 "1 "と解釈するのですか?
-
[解決済み] g++とgccの違いは何ですか?
-
[解決済み] なぜGCCは、速度の代わりにサイズに最適化すると、15-20%速いコードを生成するのですか?
-
[解決済み] LD_PRELOADのトリックとは何ですか?
-
[解決済み】-Wl,-rpath -Wlがわかりません。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
error: 'for' loop initial declaration is only allowed in C99 mode 原因と解決方法
-
エラー: 宣言されていない識別子 'bool' の使用と C コンパイラでの問題点
-
[解決済み] ⑭と⑯は何のためにあるのですか?
-
[解決済み] なぜmemsetではなくbzeroを使用するのですか?
-
[解決済み] "static const" vs "#define" vs "enum"
-
[解決済み] mallocとcallocの違い?
-
[解決済み] C言語でランダムなint型を生成するには?
-
[解決済み] C言語標準に準拠した構造体の初期化方法
-
[解決済み] C言語のi++と++iに性能差はあるのでしょうか?
-
[解決済み] フリーは、どのように無料化を知っているのですか?