11

以下测试代码在 VS 中使用调试或发布以及在 GCC 中都能正确运行。-O2它也适用于带有调试的 ICC,但在启用优化时 ( )则不正确。

#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 here\r\n");}
};

int main() {
  tClassA q;
  while(true) {
    while(q.isEmpty()) ;
    q.doSomething();
  }
  return 1;
}

它应该停在while(q.isEmpty())。但是,当-O2在 ICC(发布)下启用时,它开始无限地“做某事”。

由于这是单线程程序并且 isEmpty()应该被评估为true,我找不到 ICC 应该以这种方式运行的理由?我想念什么吗?

4

7 回答 7

9

因为while (q.isEmpty()) ;循环不包含可能导致外部可见副作用的语句,所以整个循环正在被优化而不再存在。原因是一样的:

for (int i = 0; i < 10; i++)
    ;

可以优化不存在,只要i不存在volatile(对象的存储volatile是程序“外部可见”效果的一部分)。

在 C 语言中,是否允许以这种方式优化无限循环实际上是一个突出的争论点(我不知道 C++ 的情况如何)。据我所知,在这个问题上从来没有达成共识——聪明和有见识的人已经采取了双方。

于 2010-08-20T03:16:28.497 回答
2

It sure sounds like a bug. Here's a (pretty wild) guess about what reasoning might have lead to it...

After inlining, it sees:

while (q.m_first == q.m_last) /* do nothing */ ;
do_something();

and any sequence of do nothing repeatedly ; do something can be translated to simply "do something". This falls down if the repeated part is endless (as in this case). But perhaps they don't test their compiling on examples that intentionally have endless looping ;-).

于 2010-08-20T02:55:29.210 回答
1

您构建和运行的实际代码是否有可能在 之后缺少分号while(q.isEmpty())?这肯定会导致下一行被无限调用。

于 2010-08-20T03:05:29.400 回答
1

顺便说一句,这个版本的 icc 可以满足您的需求。也就是说,它从不调用doSomething().

[9:41am][wlynch@computer /tmp] icc --version
icc (ICC) 11.0 20081105
于 2010-08-20T13:42:57.373 回答
1

C++ 标准允许删除没有副作用的循环,即使它们没有终止:

通常认为允许潜在非终止循环的转换很重要(例如,通过合并两个循环遍历相同的潜在无限集,或者通过消除无副作用的循环),即使这可能不会否则在第一个循环永远不会终止的情况下是合理的。 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2429.htm

请参阅此处的讨论:http: //blog.regehr.org/archives/161

于 2010-08-21T06:12:48.783 回答
0

Your best bet is to take the resulting binary step into it and dis-assemble the main function and see what assembly was generated. Not saying you will be able to see a bug, but you can see if something was optimized out.

于 2010-08-20T02:53:22.117 回答
-3

I think it may have been your version of gcc. I compiled your prog under 4.4.2 and it worked exactly as it should have.

于 2010-08-20T03:02:10.117 回答