8

我正在使用英特尔 C++ 编译器 12.0,并且正在编写类似于以下的程序,该程序非常简单明了。while 循环应该在第一次运行时停止。但是,当我使用英特尔编译器的 /O2 标志构建代码时,while 循环永远不会停止。如果我禁用优化,或使用 Visual C++,循环正常退出。如果我将 pt->flag 更改为 p.flag,我想这也是一样的,循环也会正常退出。我认为这与英特尔的优化有关。这是英特尔编译器中的错误吗?或者我在这里错过了什么?

#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 被修改吗?

顺便说一句:谁能让我知道如何使用英特尔编译器在 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

This is a situation known as pointer aliasing. You have a variable p and a pointer pt that points to the same thing as p. Many optimisations can be used if the compiler can assume that there is only one "name" for a given variable, and /O2 for your compiler may enable this assumption. For example, the compiler could keep all the member variables for p in registers during the loop, which obviously can't be accessed through a memory pointer.

Check your compiler documentation to find out how to tell it to not assume there are no pointer aliases. This could be a compiler switch or a #pragma.

于 2012-09-02T22:30:08.323 回答