8

私は Intel C++ コンパイラ 12.0 を使用しており、次のような非常にシンプルでわかりやすいプログラムを作成しています。while ループは、最初の実行で停止する必要があります。しかし、Intel コンパイラで /O2 フラグを使用してコードをビルドすると、while ループが停止しません。最適化を無効にするか、ビジュアル C++ を使用すると、ループは正常に終了します。pt->flag を p.flag に変更すると、同じことだと思いますが、ループも正常に終了します。Intelの最適化と関係があると思います。これは Intel コンパイラのバグですか? または私はここで何かを逃した?

#include <iostream>

using namespace std;

struct para {
    int i;  
    int flag;
};

int main(int argc, char **argv)
{
    para p;
    p.i = 0;
    p.flag = 1;

    para * pt = &p;
    cout << "loop started" << endl;

    int i;
    while (p.flag) {
        if (p.i == 0) {
            for (i=0; i<1; i++) {
                if (p.flag != 1)
                    break;
            }
            if (i==1) {
                pt->flag = 0;
            }
        }
    }
    cout << "loop stopped" << endl;
    return 1;
}

更新: 皆さんの回答に感謝します。「ポインターエイリアシング」の説明に戸惑います。p がレジスターにあり、pt がそれにアクセスできない場合、次のコードが Intel コンパイラーで while ループを中断するのはなぜですか? まず「pt->flag = 0;」i=0 であるため、有効になることはありません。第二に、それが有効であっても、「ポインターエイリアシング」は p の変更を妨げるべきではありませんか?

ところで:Intelコンパイラを使用してVisual Studioでポインタのエイリアシングをオン/オフにする方法を誰か教えてもらえますか? ありがとう!

#include <iostream>
using namespace std;
struct para {
    int i;  
    int flag;
};

int main(int argc, char **argv)
{
    para p;
    p.i = 0;
    p.flag = 1;

    para * pt = &p;
    cout << "loop started" << endl;

    int i=0;
    while (p.flag) {
        if (p.i == 0) {
            //for (i=0; i<1; i++) {
            //  if (p.flag != 1)
            //      break;
            //}
            if (i==1) {
                pt->flag = 0;
            }
        }
    }
    cout << "loop stopped" << endl;
    return 1;
}
4

1 に答える 1

6

これは、ポインタ エイリアシングと呼ばれる状況です。と同じものを指す変数pとポインターがあります。コンパイラーが特定の変数に「名前」が 1 つしかないと仮定できる場合、多くの最適化を使用でき、コンパイラーがこの仮定を有効にすることができます。たとえば、コンパイラはループ中にレジスタ内のすべてのメンバー変数を保持できますが、これは明らかにメモリ ポインターを介してアクセスすることはできません。ptp/O2p

コンパイラのドキュメントを調べて、ポインタ エイリアスがないと仮定しないように指示する方法を見つけてください。これは、コンパイラ スイッチまたは#pragma.

于 2012-09-02T22:30:08.323 に答える