4

这可能是编译器错误吗?我的环境是:

  • Win7 专业版(64 位)
  • VS2012(更新3)

我编译了下面的小控制台程序。x64 位发布/调试版本工作正常。x32 调试版本也可以正常工作。但是,x32 发布版本显示“BUG!”。

如果我禁用“整个程序优化”,这将解决问题。

有任何想法吗?

-

#include <string>
#include <iostream>


int main()
{
    std::string const buffer = "hello, world";
    std::string::size_type pos = 0;
    std::string::size_type previous_pos;


    while (pos != std::string::npos)
    {
        previous_pos = ++pos;
        pos = buffer.find('w', pos);
    } 


    if (previous_pos == std::string::npos)
    {
        std::cout << "BUG!!"<< std::endl;
    }

    return 0;
}
4

1 回答 1

4

我也可以重现这个。当 bug 出现时,代码正在测试 eax 以确定是否输出“BUG”,这与它用于 'pos' 的寄存器相同。

17:         previous_pos = ++pos;

013C12E5 公司
...

21:     if (previous_pos == std::string::npos)

00301345 cmp eax,eax
00301347 jne main+0F6h (0301366h)

但是,如果您进行更改以尝试让优化器意识到它们是不同的,那么测试就不同了。如果我在循环体的末尾添加 ++previous_pos ,那么它将 ecx 用于 previous_pos 并且错误消失了:

22:     if (previous_pos == std::string::npos)

00361349 cmp ecx,eax
0036134B jne main+0FAh (036136Ah)

如果我将查找更改为 'pos = buffer.find('w', previous_pos);' (从previous_pos而不是pos搜索,它具有相同的值)然后它使用ebx,并且错误再次消失:

21:     if (previous_pos == std::string::npos)

00191345 cmp ebx,eax
00191347 jne main+0F6h (0191366h)

所以在原文中似乎优化器错误地决定它可以对这两个变量使用 eax,尽管行 'pos = buffer.find('w', pos);' 可以将 pos 设置为与 previous_pos 不同的值。

于 2013-08-05T23:44:49.580 回答