5

この質問にはSOに関するいくつかの回答がありますが、私のものは少し異なります。重複としてマークする前に、試してみてください。

MSVC は常に /Gyコンパイラオプションを提供して、同一の関数を COMDAT セクションに折りたたむことができるようにしています。同時に、リンカーは /OPT:ICF オプションも提供します。これら 2 つのオプションを組み合わせて使用​​する必要があるという私の理解は正しいですか? つまり、前者は機能を COMDAT にパッケージ化しますが、後者は冗長な COMDATを排除します。あれは正しいですか?

はいの場合、両方を使用するか、両方をオフにしますか?

4

2 に答える 2

3

オフラインで私と連絡を取った人からの回答。これらのオプションをよりよく理解するのに役立ちました。

===================================

それは本質的に真実です。C または C++ だけを話し、メンバー関数を使用しないとします。/Gy を指定しないと、コンパイラはある意味で縮小不可能なオブジェクト ファイルを作成します。リンカーがオブジェクトから 1 つの関数だけを必要とする場合、リンカーはそれらすべてを取得します。これは、ライブラリのプログラミングにおける特別な考慮事項です。たとえば、ライブラリのユーザーに親切にする場合は、ライブラリを多数の小さなオブジェクト ファイル (通常はオブジェクトごとに 1 つの非静的関数) として記述する必要があります。ライブラリは、実際には実行されないコードを実行する必要があるため、肥大化することはありません。

/Gy を指定すると、コンパイラは COMDAT を持つオブジェクト ファイルを作成します。各関数は、ある程度ミニ オブジェクトである独自の COMDAT にあります。リンカがオブジェクトから 1 つの関数だけを必要とする場合は、その関数だけを選択できます。リンカーの /OPT スイッチを使用すると、リンカーがこの選択性を使用して何を行うかをある程度制御できますが、/Gy がないと何も選択できません。

または非常に少ない。たとえば、リンカが、オブジェクト ファイル内のコード全体であり、たまたま同一のコードを持つ関数を折りたたむことができることは、少なくとも考えられます。リンカーが、参照されているものを何も含まないオブジェクト ファイル全体を削除できることは確かに考えられます。結局のところ、これはライブラリ内のオブジェクト ファイルで行われます。ただし、実際には、COMDAT 以外のオブジェクト ファイルをリンカーのコマンド ラインに追加する場合は、参照されていなくてもバイナリでそれが必要であると言っているというルールがありました。考えられることと実際に行われたことの違いは、通常、非常に大きいものです。

それでは、簡単な答えに固執するのが最善です。リンカー オプションは、各オブジェクト ファイル内から関数 (および変数) を分離できるという利点がありますが、分離は、コンパイラの作業である COMDAT に編成されるコードとデータに依存します。

===================================

于 2016-11-14T20:29:52.940 に答える
1

2013 年 1 月に Raymond Chenが回答したとおり

/Gy のドキュメントで説明されているように、関数レベルのリンクにより、/OPT:REF を介して要求した場合、「未使用の関数」パス中に関数を破棄できます。リンクのための実際の古典的なモデルは変更されません。旗の名前は紛らわしいです。「関数レベルのリンクを実行する」ではありません。関数の開始位置と終了位置をリンカに指示することで、これを有効にするだけです。そして、それは関数レベルのリンク解除であるため、関数レベルのリンクではありません。-レイモンド

(このスニペットは、さらにいくつかのコンテキストでより意味のあるものになるかもしれません: 古典的なリンク モデルに関する投稿は次のとおりです: 12

一言で言えば - はい。1 つのスイッチを別のスイッチなしで有効にしても、目に見える影響はありません。

于 2016-11-14T07:27:30.267 に答える