Possible VS2012 compiler bug (maybe in Whole Program Optimization?)

c++, compiler-bug, compiler-optimization, visual-studio-2012

Solution

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.

Problem

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; } ```

Original source