Search code examples
visual-c++visual-studio-2012c++11access-violationstdatomic

Access violation when accessing std::atomic_ullong objects on visual studio 2012 under release mode


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!


Solution

  • 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 )