12

コードに未使用の関数があると、どのようなオーバーヘッドが発生するのでしょうか。

たとえば、デバッグログがあり、ほとんどのオブジェクトにデバッグログで使用されているToString()関数を指定するとします。

リリースビルドでは、デバッグログは使用されていません。それなら、それらのToString()関数のソースコードを削除する価値はありますか?(例えば、マクロ経由?)

それとも、実行可能ファイルをわずかに大きくするだけで、それ以外の場合はパフォーマンスに影響を与えませんか?たとえば、速度への影響はありませんか?または、コンパイラまたはリンカは、関数が使用されていない場合、関数を削除する可能性さえありますか?コンパイラまたはリンカがコードを削除しない場合、ToString()関数がインラインで定義されているとどうなりますか?おそらくそれはコードをインライン化しようとします、そして関数が決して呼び出されないので、それは消えますか?

すべての関数を静的ライブラリに保持する必要があると思いますが、実行可能ファイルにコンパイルされると、確かに多くのものがリンカーによって無視されますか?

ほぼ同様の別の注意点として、コンパイラがインライン関数をインライン化しないことを選択した場合、インライン関数は複数のコンパイルユニットで関数として定義され、リンカーは不要な定義を削除し、最後にそのうちの1つのみをリンクします。 ?

ありがとう

4

4 に答える 4

5

それはコンパイラーと、おそらく最適化レベルに依存します。

G++およびMSVC++は、未使用のインライン関数を削除しますが、未使用の非インライン関数は保持します。たとえば、通常のプログラムではSTLのごく一部しか使用しません。インラインとして定義されているため、未使用の関数はすべて削除されます。

一方、GCCは、未使用のインライン機能も含め、すべての機能を保持します。

他の質問への回答:関数が複数のコンパイル単位で何らかの形で定義されている場合、インラインとして定義されていない限り、リンカーは眉をひそめ、リンクを拒否します。

于 2011-05-26T11:27:34.807 に答える
3

1.コンパイラとリンカについて

実行可能ファイルの作成方法によって異なります。

通常、実行可能ファイルは、使用されていないものはすべて削除されます。したがって、静的に(そして適切な最適化オプションを使用して)リンクすると、関数は削除されます。

ただし、動的にリンクすると、ライブラリに関係する限り、それらはエクスポートされて使用されるため、そこに存在します。

複数の定義については、シンボルが弱いかどうかによって異なります。弱い場合、リンカーは定義の1つを選択します。そうでない場合、リンカーはそれを窒息させます。

最後に、それらはおそらくあなたのプログラムのごく一部を表しているにすぎません。

2.問題を解決する方法は?

これは難しい問題です。いつでもプリプロセッサを使用していくつかのものを削除できますが、プリプロセッサディレクティブが散らばっているコードは、読むのが非常に面倒です。

個人的には、特にリリースにもログインしているので、気にしません(他にどのように本番環境の問題を追跡しますか?)。

解決策は、問題のある関数を別のファイルで定義し、リリースでそれらをリンクしないことです。注:仮想関数は少なくともvtableで使用されているため、仮想関数では機能しないと思います。

于 2011-05-26T11:38:23.223 に答える
2

リンカは重複する関数を削除し、参照されていないデータを削除します(Microsoftリンカは、これらの設定を微調整するためのスイッチを提供します)/OPF:REF/OPT:ICF

確かに、ほとんどの場合、リンカーが不要なものや冗長なものを削除するのに優れているかどうかは問題ではありません-いくつかの小さな関数の実行可能サイズへの影響(つまり、 STLまたは他のテンプレートライブラリを多用する場合に生成されるコードは最小限です。

とはいえ、実行可能ファイルをできるだけ小さくする必要がある場合(または、デバッグコードが実際に画像サイズの大部分を占めることがわかった場合)、#ifdefすべてを実行することが、特定の関数が含まれないようにする最も簡単な方法です。コードを読むのは少し見苦しくなりますが、存在しない関数を呼び出そうとするとコンパイラエラーが発生するため、リリースビルドのデバッグコードのいくつかのスポットを誤って見逃すことがないという利点があります。

のもう1つの利点#ifdefは、移植性があり、特定のコンパイラシステムに依存しないことです:-/

于 2011-05-26T11:27:54.397 に答える
0

非仮想関数をライブラリ内の別のファイルに配置し、静的にリンクする場合は、使用されている場合にのみ実行可能ファイルに追加する必要があります。ただし、実際の違いは実行可能ファイルのサイズだけです。これはおそらく地域性、ひいてはパフォーマンスに影響を与える可能性がありますが、実際に実際に違いが生じたとしたら、私は非常に驚きます。したがって、一般的に、この手法はアプリケーションでわざわざ気にする価値はないと思います。(一方、サードパーティのライブラリを提供している場合は、すべての非仮想関数を個別のファイルに含める必要があります。)

于 2011-05-26T12:56:09.767 に答える