SCCSの “what”文字列がコンパイラによって最適化されていない

c compiler-optimization
SCCSの “what”文字列がコンパイラによって最適化されていない

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

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

Cコード内

男性から(1)何:

_
whatユーティリティーは、SCCS getコマンド(sccs-get(1)を参照)が@(#)IDキーワードの代わりに使用するパターン@(#)の出現を各ファイル名で検索し、「、>、改行、\、またはNULL文字。
_

この変数のインスタンスは1つだけであり、参照されることはありません。 誰かがこれがコンパイラによって最適化されるかもしれないことを提案しました。

私はCとCの両方で、そしてさまざまなコンパイラーでこのテクニックを長年使用してきましたが、どの文字列が最適化されるのかはまだわかりません。

なぜ最適化されていないのか、誰もが考えたことがありますか?

  3  1


ベストアンサー

無関係な文字列はほとんどコストがかからず、特にこのような場合(例えば、 コード内で実際に参照されている最初のものだけを含む一連の文字列リソースを格納します。

2


あなたのコンパイラはそのような文字列がそれらの目的のために使われることができることを知っているので、それらは離れて最適化されないかもしれません。

もちろん、プログラムの振る舞い、より正確には観察可能な振る舞いが変更されない限り、コンパイラはそれを完全に最適化することを完全に許可されています。 つまり、揮発性物質への書き込みと読み取りの順序が変わり、ライブラリ関数への呼び出しは変更されません。

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

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

編集:そのトピックについてusenetの投稿がありましたhttp://groups.google.com/group/comp.std.c / browse_thread / thread / ba1d43c76f141c2c?hl = ja [ここ]、役に立つ答えがあります。

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 */

わかりました – それはハイブリッドです。私は本当にRCSを使ってソースコードを保存していますが、ファイルを識別するためには what 'よりも ident`を選ぶことをお勧めします。自分の。 しかし、私はいくつかのファイルで宣言をしています – 全部ではありません – そしてすべてのファイルで定義をしています。 (今は覚えていませんが、一連の警告フラグの下で、変数が宣言される前に定義されたときに警告を受けていました。 その問題を解決したのはGCCの変更だったのかもしれません。私はもうわからない。)

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

私は静的定数を持つ古いシステムを好みました – しかしこれは3年以上の間私のために働きました。

2


MicrosoftのVisual C 2005には、未使用のデータに対する処理を制御するリンカオプションがあります。 `/ OPT:UNREF`は、リンカに未使用のデータを保持させます。

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

static char VersionString[] = "HELLO_WORLD 2.0";

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

1


“static”キーワードがないと、他のモジュールがその参照を宣言することがあるので(externを使って)、変数を最適化できません。 C / Cは通常ファイルを一度にコンパイルするので、コンパイラが外部参照が存在するかどうかを知る方法はありません。

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

オブジェクト形式で許可されている場合は、リンカによって未使用のグローバル変数が検出され、最適化される可能性もあります。

1


(はい、私はこれが年齢の前に尋ねられ、答えられたことを知っています。 しかし、この新しいスタイルの回答は利用可能です。

gcc(少なくとも3.3以降では)に警告を抑制するために”参照されていないことがわかっている “という変数にフラグを立てるためのコンパイラ指令attribute((unused))がありました。 used)) `他のコードが実際にそれを参照していなくても、それを使用済みとしてフラグを立てる(したがって、最適化される候補ではない)。

だからこれはあなたのためにそれをするかもしれません:

static const char what_ident[] __attribute__((used)) = "@(#) $Id$";

それでも `リンカ`がそれを最適化するのであれば、リンク時の参照に関係なく_keep_のフラグが立てられたセクションにそれを置く必要があるかもしれません。

static const char what_ident[] __attribute__((section("what"), used)) = "@(#) $Id$";

そして、リンカがfile.cの出力の中の参照されていないセクションを抑制しないように、gccオプション `-Wl、-bkeepfile:file.o`を追加します。

1


タイトルとURLをコピーしました