【发布时间】:2017-10-01 23:09:47
【问题描述】:
是否允许编译器通过将语句(不是表达式的一部分)从 volatile 访问之前移动到之后,或者从 volatile 访问之后移动到它之前来优化代码流。
参考我对SO : is volatile required for synchronous ISR access的回答
对我的回答的异议表明,使用 volatile 不会导致 C++(和 C)的通用机器确保完成之前的所有操作。
我对@987654322@的阅读
也就是说,在单个执行线程中,易失性访问不能被优化或重新排序,而另一种可见的副作用是在易失性访问之前排序或在易失性访问之后排序。这使得 volatile 对象适合与信号处理程序通信,但不适用于另一个执行线程
对于我的回答中的情况是否如此 - 单核操作以下应该是正确的。
- 结果尽可能快地可见 - 可能在某个点上对 volatile 的更改尚未写入,但如果已写入,则单核将在信号处理程序中看到它,(或ISR)。
- 兼容的 C++ 编译器无法围绕 volatile 写入重新排序操作,因为它是一种可见的副作用。
我在这个线程上的回答假设特定情况是单核 CPU,并且 C++11 不适用,所以我希望在该范围内得到答案。
【问题讨论】:
-
编译器可以重新排序所有内容,只要按程序顺序发生有序的可观察副作用(包括易失性访问) - 请参阅 [intro.execution]
-
@Cubbi 几乎没有人真正理解这样说的标准。例如,大多数 x86 编译器允许对 volatile 写入重新排序。 (查看生成的程序集,不会有内存屏障。所以写入可以按任意顺序进行。)
-
@DavidSchwartz x86 编译器正在正确地完成他们的工作,并将易失性访问视为可观察到的副作用。
-
@Cubbi 同意。但它们不能确保它们按程序顺序发生。这样做需要内存屏障,而编译器不会产生它们。它们允许写入以任何顺序发生,即使它们将它们视为可观察到的副作用。
-
@DavidSchwartz 为什么你期望有障碍?如果在这里什么都不做。没有线程间同步。 (更多关于主题,也没有编译器障碍 - 因为 OP 需要 std::atomic_signal_fence)
标签: c++ language-lawyer