web-dev-qa-db-ja.com

未使用の関数は最適化されますか?

かなり簡単な質問...最近のコンパイラは、かなりの量の最適化を行う傾向があります。また、最終出力から未使用の関数を削除しますか?

49
Paul Manta

コンパイラに依存します。 Visual C++ 9はそれを行うことができます-未使用のstatic関数はコンパイル段階で削除されます( C4505警告 もあります)、外部リンケージを持つ未使用関数はリンク段階で削除できます- リンカー設定に依存

26
sharptooth

MSVC(Visual Studioコンパイラ/リンカー)は、 /Gy および /OPT:REF

GCC/binutilsは、 -ffunction-sections -fdata-sections および --gc-sections

他のコンパイラについて知らない。

21
rubenvb

一般的なルールとして、答えは次のとおりです。

はい:未使用のstatic関数の場合。

No: unused未使用のグローバルに利用可能な関数の場合。

コンパイラは、他のコンパイルユニットがそれを参照しているかどうかを知りません。また、ほとんどのオブジェクトモジュールタイプでは、コンパイル後に関数を削除できません。また、内部参照が存在するかどうかをリンカーが通知する方法も提供しません。 (リンカーは、externalが存在するかどうかを判断できます。)いくつかのリンカーはそれを実行できますが、多くのことがこれに対して機能します。

もちろん、共有ライブラリの一部でない限り、それ自身のモジュール内の関数は、リンカによって不必要にロードされることはありません。 (明らかに、実行時に将来参照される可能性があるため。)

16
DigitalRoss

多くのコンパイラーが行いますが、特定の実装に依存します。多くの場合、デバッグビルドにはすべての機能が含まれており、デバッガー内から呼び出したり検査したりすることができます。多くの組み込みシステムコンパイラは、私が完全には理解していない理由により(*)、すべての関数が含まれている場合、オブジェクトファイルにすべての関数を含めますが、まったく使用されないオブジェクトファイルは完全に省略します。

Reflectionをサポートする言語(Java、C#、vb.netなど)では、コードに参照が存在しなくても、実行時に関数への参照を作成することができることに注意してください。たとえば、ルーチンはコンソールから文字列を受け取り、それを何らかの方法で変更し、その名前で関数の呼び出しを生成できます。コンパイラまたはリンカが、どの名前がそのように生成される可能性があるかを知る方法がないため、どの関数がコードから安全に省略される可能性があるかを知る方法はありません。ただし、コードに明示的な参照が存在しない場合、コードが関数、変数、または定数への参照を作成する定義された方法がないため、CまたはC++にはそのような困難はありません。実装によっては、連続して宣言された定数または変数が連続して格納されるように物事を調整する場合があり、したがって、以前に宣言されたものにオフセットを追加することによって、後で宣言されたものへの参照を作成する場合がありますが、そのようなトリックの動作は明示的に行われますCまたはC++標準によって保証されていません。

(*)私はそれがコンパイルとリンクを容易にすることを理解していますが、今日のコンピューターは過去数十年で実用的であったより洗練されたコンパイルとリンクのアルゴリズムを実行するのに問題はないはずです。他に何もない場合、2パスのプリコンパイル/プリリンク/コンパイル/リンクメソッドは、プリコンパイル/リンクフェーズで使用されるもののリストを生成し、その後、「実際の」コンパイル/リンクフェーズで省略できます。そうでないもの。

5
supercat

Gccでは、最適化を有効にすると、未使用の関数とデッドコードを削除できます。

Gccの最適化の詳細については、こちらをご覧ください こちら

5
rsachetto

かなり多くの時間、はい。しばしばリンカストリッピングと呼ばれます。

3
Goz

MSに関しては、リンクフェーズ中にこれを処理するのはlinkerであり、コンパイラは未使用の静的関数(ファイルスコープ)について警告する場合があります。リンカで未使用の関数を削除する場合は、 / OPT:REF オプションを使用します。

2
ralphtheninja

MSVCの下で、グローバル関数またはグローバル変数を使用すると、 __ declspec(selectany) を使用できます。

リンカオプション/ OPT:REF(最適化)が選択されている場合、コードで参照されていない関数または変数は削除されます。

1
handcoded