1. ホーム
  2. c

gccの'-l'オプションの順番はなぜ重要なのですか?重複] [重複] [重複

2023-08-07 17:41:45

質問

を使用するプログラムをコンパイルしようとしています。 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回与えることができます。