gpt4 book ai didi

c++ - std::atomic 平凡可复制结构

转载 作者:行者123 更新时间:2023-11-30 01:41:49 25 4
gpt4 key购买 nike

C++ 引用说:http://en.cppreference.com/w/cpp/atomic/atomic

std::atomic may be instantiated with any TriviallyCopyable type T

但是下面的例子在 g++ 6.2.0 下不工作

#include <atomic>
#include <functional>

struct Test11 {
int x;
};
struct Test12 {
char x;
};
struct Test13 {
long x;
};
struct Test2 {
char x;
int y;
};
struct Test3 {
int y;
long x;
};

template<typename T, typename... ARGS>
void test(ARGS&& ... args) {
static_assert(std::is_trivially_copyable<T>::value);

std::atomic<T> a;
a.store(T{std::forward<ARGS>(args)...});
}

int main() {
test<Test11>(1);
test<Test12>('\1');
test<Test13>(1L);
test<Test2>('\1',2);
test<Test3>(1,2L);
return 0;
}

编译:g++-6 -std=c++14 -latomic test.cpp

/tmp/cchademz.o: In function std::atomic<Test3>::store(Test3, std::memory_order): test.cpp:(.text._ZNSt6atomicI5Test3E5storeES0_St12memory_order[_ZNSt6atomicI5Test3E5storeES0_St12memory_order]+0x3e): undefined reference to __atomic_store_16 collect2: error: ld returned 1 exit status

g++-6 --version

g++ (Ubuntu 6.2.0-7ubuntu11) 6.2.0 20161018

特别不明白为什么Test2有效但Test3没有。

有什么想法吗?

编辑: 添加了 -latomic 标志和 g++ 版本

最佳答案

正如@TartanLlama 在其现已删除的 answer 中提到的那样, 你需要链接 libatomic :

g++-6 -std=c++14 test.cpp -latomic

您需要添加 -latomic在编译行的末尾。如果您输入 -latomic,一些编译器(链接器)可能会正常工作之前 test.cpp (例如 Coliru 上的 g++),但有些不会(参见 Why does the order in which libraries are linked sometimes cause errors in GCC?)。

免责声明:我不是链接方面的专家,所以我无法详细解释为什么它与 -latomic 一起工作。之前在某些平台上而不是其他平台上(我猜链接器是不同的,但是......)。


关于为什么如果删除 Test3 代码可以编译,这取决于编译器和体系结构。如果您使用 -O2 查看生成的 ASM和 g++6.2godbolt 上:

sub     rsp, 24
movabs rax, 8589934593
mov ecx, 5
mov DWORD PTR [rsp], 1
mov rdi, rsp
mov esi, 1
mov edx, 2
mfence
mov BYTE PTR [rsp], 1
mfence
mov QWORD PTR [rsp], 1
mfence
mov QWORD PTR [rsp], rax
mfence
call __atomic_store_16

您会看到,对于少于 8 个字节的结构(Test1XTest2),编译器可以使用 mov QWORD指令(在当今的体系结构中,一个 qword 通常是 8 个字节长),但它无法生成单个指令来处理大小严格大于 8 的情况(sizeof(Test3) 通常为 16)。

基本上,可能有一个特化 std::atomic<T> (或 std::atomic<T> 的某些操作)在 g++1T是“小”,“小”的定义可能与体系结构相关。

免责声明:同样,我不是 <atomic> 方面的专家所以这主要来自关于在 Godbolt 上生成的 ASM 和 g++ 行为的实验和 clang在 Coliru 上。

1 clang有一个 __atomic_store_8程序和 __atomic_store程序,没有-latomic它不会为 Test2 编译和 Test3 .然而它设法编译Test13即使sizeof(Test13)是 8 所以它不使用 __atomic_store_8对于某些结构。 icc具有完全不同的行为,不会生成任何 call (无法在 Coliru 上测试,但您可以在 Godbolt 上查找)。

关于c++ - std::atomic 平凡可复制结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40739306/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com