C++ 为什么std::atomic<;双倍>;isn';在使用clang编译时是否未实现?

C++ 为什么std::atomic<;双倍>;isn';在使用clang编译时是否未实现?,c++,c++11,double,stdatomic,C++,C++11,Double,Stdatomic,考虑以下代码: #包括 内部主(空){ std::原子双倍体; a双倍=6.0; } G++编译得很好,而clang++生成以下内容: clang++ -std=c++11 Main.cpp /tmp/Main-d4f0fc.o: In function `std::atomic<double>::store(double, std::memory_order)': Main.cpp:(.text._ZNSt6atomicIdE5storeEdSt12memory_order[_

考虑以下代码:

#包括
内部主(空){
std::原子双倍体;
a双倍=6.0;
}
G++编译得很好,而clang++生成以下内容:

clang++ -std=c++11 Main.cpp 
/tmp/Main-d4f0fc.o: In function `std::atomic<double>::store(double, std::memory_order)':
Main.cpp:(.text._ZNSt6atomicIdE5storeEdSt12memory_order[_ZNSt6atomicIdE5storeEdSt12memory_order]+0x31): undefined reference to `__atomic_store_8'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
clang++-std=c++11 Main.cpp
/tmp/Main-d4f0fc.o:在函数“std::atomic::store(double,std::memory_order)”中:
Main.cpp:(.text.\u znst6atomicidate5storeedst12memory\u顺序[\u znst6atomicidate5storeedst12memory\u顺序]+0x31):对“原子存储”的未定义引用
叮当声:错误:链接器命令失败,退出代码为1(使用-v查看调用)

它们是否与同一标准库链接?

如果
clang++-stdlib=libstdc++
不能解决您的问题,请与
-latomic
链接以实现这些功能

不过,请尝试让编译器内联8字节和更窄的原子,因为库函数有潜在的巨大缺点

请注意,库函数不支持比
内存顺序\u seq\u cst
弱的内存顺序,因此它们总是在x86上使用
mfence
,即使源代码使用了
松弛


32位x86版本的
\uuu原子存储\u 8
更糟糕:它使用
锁cmpxchg8b
而不是SSE或x87 8字节存储。这使得它即使未对齐也能工作,但会带来巨大的性能损失。它还有两个冗余的
锁或[esp],0
指令作为额外的屏障,用于从堆栈加载其参数。(我正在查看Arch Linux上gcc7.1.1中的
/usr/lib32/libatomic.so.1.2.0

讽刺的是,当前的gcc-m32(在C11模式下,不是C++11)在结构内部对齐
atomic\u llong
,但内联
movqxmm
加载/存储,因此它实际上不是原子的。()

当前的clang-m32即使在结构内部也会将原子长度对齐到8字节(与i386系统V ABI只对齐到4B的常规长度不同)。具有讽刺意味的是,clang生成对库函数的调用,库函数使用
锁cmpxchg8b
(),因此它实际上是原子的,即使在缓存线拆分的情况下也是如此。()

因此,即使某些gcc编译的代码将指针传递给未对齐的
\u原子长
,clang也是安全的。但是它不同意gcc关于结构布局的观点,因此只有当它直接获得指向原子变量的指针,而不是包含结构的指针时,这才有帮助



相关:

大多数clang使用libc++,而gcc使用libstdc++。因此,如果您在仅安装了gcc标准库的系统上使用clang进行编译,则可能需要将
-lstdc++
标志传递给clang。是的,
clang++-std=c++11-lstdc++Main.cpp
确实编译程序。因此,问题在于
libc++
没有实现该功能,而
libstdc++
拥有该功能?使用
clang++-stdlib=libstdc++
clang++-stdlib=libc++
确保标题与链接的库兼容@5gon12eder:不要使用
-lstdc++
。如果
libc++
头文件具有依赖于libc++内部结构的某个内容的内联定义,并且它最终会被非内联
libstdc++
函数生成的某个内容的指针调用,则(至少在理论上)可能会被破坏(反之亦然)。顺便说一句,libc++现在支持
std::atomic
。对于x86,它编译为与libstdc++相同的asm,不幸的是,这不是非常高效(使用clang4.0或gcc7):请参阅以获取更多.FWIW,-latomic的帮助(ubuntu 17.04、clang5.0.1-m32、所有安装的gcc多库等)。