编译器是否允许像Intel C ++编译器一样去除无限循环
以下测试代码可以在VS中正确执行,包括调试或发布,以及GCC中。 它也适用于具有调试功能的ICC,但在启用优化功能时( -O2
)则不会。
#include <cstdio>
class tClassA{
public:
int m_first, m_last;
tClassA() : m_first(0), m_last(0) {}
~tClassA() {}
bool isEmpty() const {return (m_first == m_last);}
void updateFirst() {m_first = m_first + 1;}
void updateLast() {m_last = m_last + 1;}
void doSomething() {printf("should not reach herern");}
};
int main() {
tClassA q;
while(true) {
while(q.isEmpty()) ;
q.doSomething();
}
return 1;
}
它应该停在while(q.isEmpty())
。 然而,当根据ICC(发布)启用-O2
时,它开始无限地“做某事”。
由于这是单线程程序,并且isEmpty()
应该被评估为true
,所以我没有理由认为ICC应该以这种方式行事? 我错过了什么吗?
因为while (q.isEmpty()) ;
循环不包含任何可能导致外部可见副作用的语句,整个循环将被优化为不存在。 这是相同的原因:
for (int i = 0; i < 10; i++)
;
只要i
不是volatile
(存储到volatile
对象是程序的“外部可见”效果的一部分)。
在C语言中,它实际上是一个突出的争论点,是否允许以这种方式优化无限循环(我不知道C ++的情况)。 据我所知,在这个问题上一直没有达成共识 - 聪明和知识渊博的人已经采取双方。
这听起来像一个错误。 这是一个(非常狂野)猜测可能导致它的原因...
内联后,它看到:
while (q.m_first == q.m_last) /* do nothing */ ;
do_something();
以及任何do nothing repeatedly ; do something
序列do nothing repeatedly ; do something
do nothing repeatedly ; do something
可以翻译成简单的“做点什么”。 如果重复的部分是无穷无尽的(如在这种情况下),这会下降。 但也许他们不会测试他们编译的故意有无穷循环的例子;-)。
任何你构建和运行的实际代码在while(q.isEmpty())
之后缺少分号的while(q.isEmpty())
? 这肯定会导致下一行被无限调用。
上一篇: Are compilers allowed to remove infinite loops like Intel C++ Compiler with