2

コンパイラの最適化について聞いた。

たとえば、次の場合です。

while(myBool)
    doStuff();

コンパイラは、whileループ内でmyBoolを変更しないことを認識しています。コンパイラは、myBoolを1回読み取るだけで、毎回チェックするわけではありません。

これはvolatileキーワードの影響を受ける可能性がありますか?

だから私はコンパイラを「だまして」みましたが、値は変更されていないと思います。

int main()
{
    struct st 
    {
        int a;
        int b; //I want to make difference by writing volatile here
    }s;

    s.b = 1;

    while(s.b > 0)
    {
        *((&s.a)+1) = 0;
        std::cout << "test" << std::endl;
    }
}

しかし、完全な最適化がオンになっている場合でも(vs2012)、これはコンパイラーをだましません。これはおそらく非常に不完全なトリックです:)

どうすればそれをだますことができますか?それも可能ですか?

私の目標は、キーワードを使用して「test」を出力し、volatileキーワードを使用せずに「test」を無限に出力する、単純なシングルスレッドプログラムを作成することです。

編集:残念ながら、私はアセンブラが苦手なので、メモリの読み取りが最初に最適化されていると、本当に読み取ることができません:)

4

3 に答える 3

2

あなたがしているのは未定義の振る舞いです。代わりにs.b書き込みでアクセスすることはできません。これは、それらの間にパディングバイトがないという保証がないためです。*((&s.a)+1)s.as.b

パディングを強制的に行わないようにする場合は、コンパイラオプションを調べてください。GCC / Clangの場合、構造をで宣言し__attribute__((packed))ます。MSVCの場合、#pragma packディレクティブを使用します。

そのコードを使用してs.bアクセスする正当な理由はありません。s.aこの場合、s.b直接アクセスしない正当な理由があると仮定して、実際に行う必要があるのは、配列(volatile必要に応じて)を使用することです。配列は、特別な属性/プラグマを必要とせずに、メモリ内で連続していることが保証されています。

さらに、コンパイラーは場合によっては特定の最適化を行いません。iが変数であり、に書き込みを行ったa[i]後に読み取りを行うと、コンパイラーはそれが書き込まれただけa[1]ではないと想定できないため、次のことができなくなります。a[1]レジスタにキャッシュします。一方、2つの無関係な変数がaありb、書き込みを行って*(&a+1)から読み取りを行う場合b、コンパイラそれbが単に書き込まれただけではないと見なします。これが未定義動作である非常に良い理由の1つ*(&a+1)です。これは、コンパイラーが誤った仮定を行い、プログラムが奇妙な方法で動作する原因となるためです。

于 2012-08-30T18:58:27.610 に答える
1

コンパイラが値がほぼ同じであると想定する方法(この例ではtrue)を確認して、コンパイラがこの値を最適化する方法を尋ねていると思います。その場合、コンパイラ固有のキーワードのセットを探しています。これは私がg++で使用するものです

#define predict_true__(exp)     __builtin_expect((exp), 1)
#define predict_true__(exp)       (exp)

このようにあなたはすることができます

while ( predict_true__( myBool ))
    doStuff() ;

myBoolがtrueの場合、効率的に実行されます。それがお役に立てば幸いです。ビジュアルを使用する場合に何を見るかがわかります。

追加:私はそれについて話している次の投稿を見つけました。しかし、それは悲しい話だと思います。MSVCと同等である可能性が高い/ありそうもない

于 2012-08-30T18:47:09.460 に答える
0

簡単な答えはstructs、メモリ内で隣接していることが保証されていないということです。配列はです。そのような構造体にはアクセスできません!

役立つかもしれないSOの質問:構造体のポインタ演算。これを実行できない方法とその理由について、もう少し詳しく説明します。しかし、要約すると、構造体のフィールド間にパディングがある場合とない場合があります。私はその質問に対するチャーリーの答えが特に好きです。

于 2012-08-30T19:00:19.853 に答える