Cコンパイラは、.aファイルに静的にリンクするときに未使用の関数を削除しますか?

Cコンパイラは、.aファイルに静的にリンクするときに未使用の関数を削除しますか?

main.cに静的にリンクされたライブラリがあるとしますlibmine.a。ライブラリへの静的リンクのため、ライブラリ関数はコンパイル時にデフォルトの実行可能ファイルに含まれます。

libmine.a未使用の関数が提供されている場合、main.cコンパイラ(GCCなど)はこれらの関数を破棄しますか?

この質問は、静的ライブラリを使用すると、実行可能ファイルがより大きくなるという「共通メッセージング」に触発されたので、コンパイラが少なくともアーカイブで使用していないコードを削除するかどうか疑問に思います。

答え1

デフォルトでは、リンカはオブジェクトファイル全体を処理します。あなたの例では、実行可能ファイルには、最終的にmain.c()のコードと、使用されるすべてのmain.o機能を提供(配信)するために必要なすべてのオブジェクトファイルlibmine.a(オブジェクトファイルのアーカイブ)が含まれますmain.c

したがって、リンカーに必ずしも以下を含める必要はありません。みんなただし、libmine.a利用可能な粒度は関数(デフォルト)ではなく、オブジェクトファイル(厳密にはセクション)です。その理由は、.c特定のファイルをオブジェクトファイルにコンパイルすると、ソースコードの情報が失われるためです。特に、関数の終わりは保存されず、関数の開始のみが保存され、複数の関数を組み合わせることができるためです。 、機能を使用していないときに実際に削除できる項目をオブジェクトファイルで決定することは困難です。

ただし、コンパイラとリンカーは、必要な追加情報にアクセスできれば、より良い操作を実行できます。たとえば、1980年代のMacのLightspeedCプログラミング環境では、プロジェクトをライブラリとして使用することができ、その場合は完全なソースコードがあったため、実際に必要な機能のみを含めることになりました。

より近代的なシステムでは、リンカが関数を個別に処理できるようにするオブジェクトファイルを生成するようにコンパイラに指示できます。 GCCを使用してオプションが有効なファイルをビルドし、.o最終プログラムをそのオプションに関連付けます。これは、特定のクラスの最適化を防止するのに特に影響します。-ffunction-sections -fdata-sections--gc-sectionsGCCで使用されていない関数を破棄します。もっと学ぶ。

最新のコンパイラとリンカで利用可能なもう1つのオプションは、リンク時間の最適化です-flto。最適化が有効になっている場合(例えば -O2オブジェクトファイルをコンパイルするとき、リンカには結果のバイナリに使用されていない関数は含まれません。そうでなくても-ffunction-sections -fdata-sections

答え2

はい。ただし、これは機能ではなくモジュールレベルにあります。

たとえば、foo_goo.cとbar.cという2つのソースファイルがあります。

// foo_goo.c
int foo() { .. };
int goo() { .. };
// bar.c
int bar() { .. };

これを合計してfoo_goo.oアーカイブにbar.o保存します。.olibmine.a

これで関数main()を呼び出すだけですfoo()

// main.c
int main(int argc, char **argv) {
   return foo();
}

このソースファイルをにコンパイルしmain.oてリンクします.a

リンカはfoo()モジュールの関数を見てfoo_goo.o使用し、関数が参照さmain()foo()goo()関数は最終バイナリに追加されますが、参照されません。bar.o参照された名前がないため無視されます。

答え3

これはコンパイラとは何の関係もありません。静的リンクを使用している場合、リンカは必要なすべてのオブジェクトを1つのファイルに保存します。

これは C プログラムの main() 関数、main が使用できるすべてのもの、main が使用できる一部の機能などになります。呼び出せない関数やアクセスできないオブジェクトがある場合、リンカはそれを無視できます。オブジェクトファイルに呼び出すことができる5つの関数と呼び出すことができない10の関数が含まれている場合、リンカは最初の5つだけを含めることができます。

関連情報