在发布模式下访问visual studio 2012上的std :: atomic_ullong对象时发生访问冲突

时间:2013-09-15 07:32:08

标签: visual-c++ visual-studio-2012 c++11 access-violation stdatomic

这是我的代码(删除了一些未发布的部分):

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

它在调试模式下编译并运行良好。但是,在我切换到发布模式后,我在运行时不断收到访问冲突异常。如果我将atomic_ullong更改为atomic_ulong或atomic_uint,它会毫无问题地运行,这太奇怪了。但这两者的长度还不够。所以任何人都知道为什么会这样,以及如何解决它?请帮忙!

1 个答案:

答案 0 :(得分:1)

一个相当明显的错误代码生成案例。在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  

不寻常,但不是一个直接的问题。问题在于结语:

mov         esp,ebp  
pop         ebp  
mov         esp,ebx  
pop         ebx  
ret  

EBX用作函数体中的临时寄存器。到目前为止,它的值恰好是1。那么ESP变为1,然后POP试图从中读取,显然是虚假的,地址

我建议您在http://connect.microsoft.com/visualstudio报告此问题。同时,作为一种直接的解决方法,如果您将func#pragma optimize( "", off )#pragma optimize( "", on )

包围在一起,则会有效