3

展開された実行可能ファイルまたは共有ライブラリのバージョン番号を確認できるように、バイナリ オブジェクト内に what 文字列を埋め込もうとします。通常、標準の CVS Id 情報をこの文字列に埋め込みます。たとえば、以下を埋め込む場合があります。

const char cvsid[] = "@(#)OUR_TEAM_staging_remap_$Revision: 1.30 $ $Name:  $";

Cコード内。

男から (1) 何:

what ユーティリティーは、SCCS get コマンド (sccs-get(1) を参照) が @(#) ID キーワードを置換するパターン @(#) の出現を各ファイル名で検索し、", >, NEWLINE、\、または NULL 文字。

この変数のインスタンスは 1 つだけであり、参照されることはありません。これはコンパイラによって最適化される可能性があると誰かが示唆しました。

私はこの手法を C と C++ の両方で、さまざまなコンパイラで長年使用してきましたが、最適化された文字列をまだ見ていません。

最適化されていない理由を知っている人はいますか?

4

6 に答える 6

2

最近まで (私は 2005 年半ばに問題を発見しました)、以下を使用することができました:

static const char sccs[] = "@(#)%W% %E%";

または、ソースコードとGCCおよび他のほとんどのコンパイラで同様のものは最適化されません。その頃の GCC のリリース (おそらく 2005 年 4 月に開始された GCC 4.0.x) から、これらの定数文字列はバイナリから除外されました。そのため、ソース コードを変更して変数を外部から見えるようにする必要がありました。コンパイラがオブジェクト ファイルだけを見て、文字列が未使用であると結論付けることはできません。したがって、私のファイルには次のものが含まれています。

#ifndef lint
extern const char jlss_id_filename_c[];
const char jlss_id_filename_c[] = "@(#)$Id$";
#endif /* lint */

OK - それはハイブリッドです。私はソース コードを保存するために RCS を実際に使用していますが、ファイルを識別するためwhatにRCS を使用することを好みます。しかし、すべてではなく一部のファイルに宣言があり、すべてのファイルに定義があります。(いくつかの警告フラグのセットの下で、今は覚えていませんが、変数が宣言される前に定義されたときに警告を受けていました。その問題を解決したのは GCC の変更であった可能性があります。これ以上はわかりません。)identwhatwhatident

新しいファイルを作成すると、テンプレート ジェネレーターが「filename_c」を、生成されるファイルの適切な名前に置き換えます。ヘッダーについても同様ですが、複数の定義を避けるために、識別文字列は 1 つのファイルにのみ埋め込まれます。

私は静的定数を使用する古いシステムを好みましたが、これは 3 年以上私にとってはうまくいきました。

于 2009-01-31T07:22:04.823 に答える
2

通常、これは発生しません。余分な文字列はほとんどコストがかからず、特にこのような場合に役立ちます (たとえば、コードで実際に参照される最初の文字列リソースのみを格納するなど)。

于 2009-01-27T17:36:29.723 に答える
2

コンパイラは、そのような文字列がそれらの目的に使用できることを認識しているため、最適化されていない可能性があります。

もちろん、プログラムの動作、より正確には観察可能な動作が変更されない限り、コンパイラはそれを最適化することが完全に許可されています。つまり、volatile への書き込みと読み取りのシーケンス、およびライブラリ関数の呼び出しは変更されません。

アプリでそのような文字列を最適化することで、動作は変わらないと思います。しかし、コンパイラは使いやすく、ユーザーの邪魔にならないようにしたいと考えています。そのため、便利な拡張機能も含まれています。ただし、場合によっては最適化されていないことを確認したい場合は、コンパイラの拡張機能を調べてください。GCC にはunused属性があり、未使用のオブジェクトに対して警告を発しません。おそらく、それまたは同様のことが、変数が最適化されていないのに役立つ可能性があります。

言語の観点からは、コンパイラにそれを強制的に保持させるためのユーティリティがあります。

編集: そのトピックに関する usenet の投稿がありましたここ、有用な回答があります。

于 2009-01-27T17:41:57.497 に答える
1

MicrosoftのVisualC++ 2005には、未使用のデータに対する処理を制御することになっているリンカーオプションがあります。 /OPT:UNREFリンカーに未使用のデータを保持させ、/OPT:REFそれを排除できるようにします。

しかし、私の簡単なテストでは、オプションはステートメントに影響を与えませんでした

static char VersionString[] = "HELLO_WORLD 2.0";

文字列は、フラグに関係なく、リリースバイナリとデバッグバイナリの両方に表示されました。

于 2009-01-27T18:12:16.640 に答える
1

"static" キーワードがないと、別のモジュールが (extern を使用して) 参照を宣言する可能性があるため、変数を最適化して取り除くことはできません。通常、C/C++ は一度に 1 ファイルずつコンパイルされるため、外部参照が存在するかどうかをコンパイラが知る方法はありません。

static キーワードを追加することにより、名前が使用中のコンパイル内でのみ表示され、最適化が可能になることをコンパイラーに伝えます。

リンカーは未使用のグローバル変数を検出し、オブジェクト形式で許可されている場合はそれを最適化することもできると思いますが、誰かがそうするかどうかはわかりません。

于 2009-07-21T22:30:39.590 に答える