This is my code(removed some unreleated parts though):
#include <atomic>
#include <math.h>
#include <iostream>
using namespace std;
struct Profiler
{
private:
Profiler() {}
Profiler(const Profiler& other) {}
Profiler operator = (const Profiler& other) { return *this; }
public:
static atomic_ullong a;
static atomic_ullong b;
};
atomic_ullong Profiler::a = { (unsigned long long)0 };
atomic_ullong Profiler::b = { (unsigned long long)0 };
bool func()
{
Profiler::a++;
float det = rand();
if (abs(det) < numeric_limits<float>::epsilon())
return false;
Profiler::b++;
return true;
}
int main(int argc, char** argv)
{
bool result = func();
cout << result << endl;
system("pause");
return 0;
}
It compiles and runs well under debug mode. However, after I switch to release mode, I keep getting access violation exceptions when it runs. It's so weird that it runs without a problem if I change atomic_ullong to atomic_ulong or atomic_uint. But the length of those two is just not enough. So anyone know why this is happening and how to solve it? Please help!
A rather clear case of bad code generation. There's a pretty weird prolog at the top of func
push ebx
mov ebx,esp
sub esp,8
and esp,0FFFFFFF8h
add esp,4
push ebp
mov ebp,dword ptr [ebx+4]
mov dword ptr [esp+4],ebp
mov ebp,esp
sub esp,18h
Unusual, but isn't an immediate problem. The problem is in the epilog:
mov esp,ebp
pop ebp
mov esp,ebx
pop ebx
ret
EBX
is used as a scratch register in the body of the function. Its value happens to be 1 by this point. So then ESP
becomes 1, and then POP
tries to read from that, obviously bogus, address
I suggest you report the issue at http://connect.microsoft.com/visualstudio. Meanwhile, as an immediate workaround, it works if you surround func
with #pragma optimize( "", off )
and #pragma optimize( "", on )