首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >是否可以保证保存对易失性结构的独立成员的写入顺序?

是否可以保证保存对易失性结构的独立成员的写入顺序?
EN

Stack Overflow用户
提问于 2020-12-14 20:19:47
回答 2查看 1.4K关注 0票数 34

假设我有这样一个结构:

代码语言:javascript
复制
volatile struct { int foo; int bar; } data;
data.foo = 1;
data.bar = 2;
data.foo = 3;
data.bar = 4;

所有的作业都保证不会被重新排序吗?

例如,如果没有易失性,编译器显然可以将其优化为两个指令,顺序不同,如下所示:

代码语言:javascript
复制
data.bar = 4;
data.foo = 3;

但是对于易失性,编译器不需要这样做吗?

代码语言:javascript
复制
data.foo = 1;
data.foo = 3;
data.bar = 2;
data.bar = 4;

(例如,将成员视为独立的不相关的易失性实体-并进行重新排序,我可以想象,如果foo和bar处于页面边界,它可能试图提高引用的局部性。)

另外,对于当前版本的C和C++标准,答案是否一致?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-12-14 20:30:39

C

他们不会被重新排序。

C17 6.5.2.3(3)说:

后面的后缀表达式。运算符和标识符指定结构或联合对象的成员。值是命名成员的值,97),如果第一个表达式是lvalue,则为lvalue。如果第一个表达式具有限定类型,则结果具有指定成员类型的如此限定版本。

由于data具有volatile-qualified类型,data.bardata.foo也是如此。因此,您将对volatile int对象执行两次赋值。在6.7.3脚注136中,

对被声明为volatile的对象的操作不应由实现“优化”或重新排序,除非表达式的计算规则允许。

一个更微妙的问题是,编译器是否可以用一条指令来分配它们,例如,如果它们是相邻的32位值,那么它是否可以使用64位存储来设置这两者?我不这么认为,至少GCC和Clang没有尝试过。

票数 30
EN

Stack Overflow用户

发布于 2020-12-15 09:31:12

如果您想在多个线程中使用这一点,那么有一个重要的问题。

虽然编译器不会重新排序对volatile变量的写入(如Nate Eldredge的回答中所描述的那样),但还有一点可能发生写入重新排序,那就是CPU本身。这取决于CPU体系结构,下面的几个例子如下:

英特尔64

Intel 64架构内存排序白皮书

虽然商店指令本身没有重新排序(2.2):

  1. 商店不会与其他商店重新定购。

它们可能以不同的顺序在不同的CPU中可见(2.4):

Intel 64内存排序允许这两个处理器以不同的顺序查看两个处理器的存储。

AMD 64

AMD64(这是常见的x64)在规格中有类似的行为。

一般情况下,不允许乱写.按照顺序执行的写指令不能将其结果提交(写)到内存,直到所有以前的指令按程序顺序完成为止。然而,处理器可以在私有缓冲区(软件不可见)中保存无序写入指令的结果,直到该结果被提交到内存中。

PowerPC

我记得在使用PowerPC处理器的Xbox 360上必须小心

虽然Xbox 360 CPU不重新排序指令,但它确实重新安排了写入操作,这些操作在指令本身之后完成。PowerPC内存模型特别允许这种写入的重新排列。

为了避免以可移植的方式重新排序,您需要使用记忆栅栏,如C++11、篱笆或C11 篱笆。没有它们,从另一个线程中看到的写入顺序可能是不同的。

另见https://stackoverflow.com/questions/6319146/c11-introduced-a-standardized-memory-model-what-does-it-mean-and-how-is-it-g

维基百科https://en.wikipedia.org/wiki/Memory_barrier#Out-of-order_execution_versus_compiler_reordering_optimizations的文章中也提到了这一点:

此外,由于缓存、缓存一致性协议和轻松的内存排序,其他处理器或内核也不能保证易失性读写的顺序相同,这意味着仅仅易失性变量甚至不能作为线程间标志或互斥变量工作。

票数 17
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65295907

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档