我在Windows XP上使用MinGW 4.6.2并且我遇到了std :: atomic的一些奇怪行为。 情况如下:
最终结果是线程A读取的值不是线程B设置的值。
如果我删除了std :: atomic(即将变量保存为指针),它会按预期工作。更有趣的是,如果我将模板参数设置为 unsigned long 并将指针转换为 T * ,它将按预期工作。
我正在使用赋值运算符来设置值,并使用load成员来获取值。
我是否错过了带有T *作为参数的std :: atomic应该如何工作或者这种破坏的行为?
修改
一些代码
#include <boost/thread.hpp>
#include <atomic>
using namespace std;
void* vptr;
std::atomic<unsigned int> aui;
std::atomic<void*> aptr;
void foo()
{
vptr = (void*) 0x123;
aui = (unsigned int) 0x123;
aptr = (void*) 0x123;
}
int main(int argc, char* argv[])
{
boost::thread threadA;
vptr = nullptr;
aui = 0;
aptr = nullptr;
threadA = boost::thread(foo);
threadA.join();
cout << vptr << " " << (void*)aui.load() << " " << aptr.load();
return 0;
}
输出为:0x123 0x123 0x41d028
答案 0 :(得分:2)
我用MinGW 4.6.1重现了你的问题(并发现它在4.7.0中修复)。如果您无法移动到已修复问题的较新MinGW,您应该能够修改lib/gcc/mingw32/4.6.2/include/c++/bits/atomic_0.h
标头的_ATOMIC_STORE_
宏的定义,如此(假设4.6.2中的标头)类似于4.6.1):
#if 0 /* disable the original broken macro */
#define _ATOMIC_STORE_(__a, __n, __x) \
({typedef __typeof__(_ATOMIC_MEMBER_) __i_type; \
__i_type* __p = &_ATOMIC_MEMBER_; \
__typeof__(__n) __w = (__n); \
__atomic_flag_base* __g = __atomic_flag_for_address(__p); \
__atomic_flag_wait_explicit(__g, __x); \
*__p = __w; \
atomic_flag_clear_explicit(__g, __x); \
__w; })
#else
#define _ATOMIC_STORE_(__a, __n, __x) \
({typedef __typeof__(_ATOMIC_MEMBER_) __i_type; \
__i_type* __pxx = &_ATOMIC_MEMBER_; \
__typeof__(__n) __w = (__n); \
__atomic_flag_base* __g = __atomic_flag_for_address(__pxx); \
__atomic_flag_wait_explicit(__g, __x); \
*__pxx = __w; \
atomic_flag_clear_explicit(__g, __x); \
__w; })
#endif
问题似乎是名为__p
的宏中的局部变量,当使用宏参数__p
的名为__n
的变量调用宏时,这显然会造成混淆。当__n
扩展为__p
时,扩展宏不会访问调用者“传递”的变量,而是访问本地变量。
答案 1 :(得分:0)
这可能是http://gcc.gnu.org/bugzilla/show_bug.cgi?id=51811 - 已在GCC 4.7中修复
您能否显示导致问题的代码?