コンパイラが最適化を実行するとき、呼び出されない関数は省略されますか? プログラムに不必要な肥大化をもたらすため、不要なファイルを含めないようにと書かれているものを読んだことを覚えています。コンパイラがそれらを削除しない理由であり、最新のコンパイラのほとんどはおそらく余分な未使用の関数を削除すると思います。
3 に答える
一般的に言えば、答えは「いいえ」です。ただし、一部のコンパイラは、特定のケースで一部の関数を削除します。また、リンカは、そのファイル内の関数を必要としないソース ファイル内にある静的にリンクされたライブラリからの関数も含めません。
通常排除される 1 つの一般的なケースは、決して呼び出されず、誰のアドレスも取得されない静的関数です。もう 1 つは、呼び出されるすべての場所でインライン化され、誰のアドレスが取得されることもない静的関数です。
それは完全にコンパイラ次第です。
しかし、一般に、コンパイラはプログラム全体を把握して包括的なコール グラフを作成することはできないため、これを行うのは非常に困難です。そしてリンカーは十分にスマートではありません。
さらに、一部のファイルは最終的にライブラリの一部になる場合があります。そして、ライブラリの全体的な目的は、ライブラリ自体から呼び出されない一連のコードを持つことです。コンパイラは、特定のコードがライブラリに含まれるかどうかをコンパイル時に判断できません。繰り返しますが、「外部リンケージ」を持つ関数の場合、それらが使用されていない場合、それらを除外するのはリンカー次第です。
それはコンパイラに大きく依存しますが、はい、一部のセットアップでは、コンパイラは呼び出されない関数を完全に排除できます。コンパイラは、関数が実際に呼び出されないようにする必要があります。
具体的には、マークされた関数はstatic
非常に簡単に削除できます。同じ翻訳単位を調べるだけです。関数が別の翻訳単位から呼び出される可能性がある場合は、さらに困難になります。Visual C++ には、「関数レベルのリンク」と呼ばれるこのための特別な設定と、参照されていない関数を削除するためのリンカー設定があります。これら 2 つを一緒に使用すると、参照されていない関数は完全に削除されます。
それはできます。C++ コンパイラは、単にas-ifルールの下で動作します。結果のプログラムが標準の指示どおりに動作する限り、コンパイラはそこにたどり着くために好きなことを何でもできます。
準拠する実装は、抽象マシンの観察可能な動作をエミュレートする (のみ) 必要があります。
関数が呼び出されない場合、もちろんコンパイラはそれを取り除くことができますが、そうするかどうかは完全にコンパイラ次第です。ただし、C++ のコンパイル モデルでは、翻訳単位を個別にコンパイルする必要があります。多くの場合、関数が他の翻訳単位から呼び出されていないことをコンパイラが知ることは不可能または非常に困難です。