Could this be a compiler error? My environment is:

  • Win7 pro (64-bit)
  • VS2012 (update 3)

I compile the tiny console program below. Things work fine for x64 bit release/debug builds. The x32 debug build also works just fine. The x32 release build, however displays 'BUG!'.

If i disable 'Whole Program Optimization' that will fix the issue.

Any ideas?

-

#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;
}
有帮助吗?

解决方案

I can reproduce this too. When the bug manifests, the code is testing eax to deterimine whether to output "BUG", which is the same register it's using for 'pos'.

17:         previous_pos = ++pos;

013C12E5 inc eax
...

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

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

However if you make a change to try to get the optimzer to realise they are distinct then the test is different. If I add ++previous_pos at the end of the loop body then it uses ecx for previous_pos and the bug goes away:

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

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

If I change the find to 'pos = buffer.find('w', previous_pos);' (searching from previous_pos instead of pos, which has the same value) then it uses ebx, and again the bug goes away:

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

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

So it seems in the original that the optimiser is erroneously deciding that it can use eax for both of those variables, despite the line 'pos = buffer.find('w', pos);' that can set pos to a different value than previous_pos.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top