相关疑难解决方法(0)

C++ volatile关键字是否引入了内存栅栏?

我知道volatile通知编译器可能会更改值,但为了完成此功能,编译器是否需要引入内存栅栏才能使其工作?

根据我的理解,易失性对象的操作顺序不能重新排序,必须保留.这似乎暗示一些内存栅栏是必要的,并且没有真正解决方法.我说的是对的吗?


这个相关问题上有一个有趣的讨论

乔纳森威克利写道:

...对于不同的volatile变量的访问不能由编译器重新排序,只要它们出现在单独的完整表达式中......对于线程安全而言volatile是无用的,但不是由于他给出的原因.这不是因为编译器可能会重新排序对易失性对象的访问,而是因为CPU可能会重新排序它们.原子操作和内存屏障阻止编译器和CPU重新排序

大卫·施瓦茨回答的评论:

...从C++标准的角度来看,编译器执行某些操作与编译器发出导致硬件执行某些操作的指令之间没有区别.如果CPU可能重新排序对volatiles的访问,则标准不要求保留其订单....

... C++标准没有对重新排序有什么区别.你不能争辩说CPU可以重新排序它们没有可观察到的影响,所以没关系--C++标准将它们的顺序定义为可观察的.如果编译器生成的代码使平台能够满足标准要求,则编译器在平台上符合C++标准.如果标准要求对挥发物的访问不能重新排序,则重新排序它们的平台不符合要求....

我的观点是,如果C++标准禁止编译器重新排序对不同易失性的访问,理论上这种访问的顺序是程序可观察行为的一部分,那么它还要求编译器发出禁止CPU执行的代码所以.该标准没有区分编译器的作用以及编译器生成的代码使CPU执行的操作.

这确实产生了两个问题:它们中的任何一个是"正确的"吗?实际的实现到底做了什么?

c++ multithreading volatile c++11

80
推荐指数
8
解决办法
1万
查看次数

C++中的易失性11

在C++ 11标准中,机器模型从单线程机器变为多线程机器.

这是否意味着static int x; void func() { x = 0; while (x == 0) {} }优化输出读取的典型示例将不再发生在C++ 11中?

编辑:对于那些不知道这个例子的人(我非常惊讶),请阅读:https://en.wikipedia.org/wiki/Volatile_variable

EDIT2:好的,我真的很期待所有知道volatile这个例子的人.

如果您使用示例中的代码,则循环中读取的变量将被优化,使循环无限.

解决方案当然是使用volatile它会强制编译器在每次访问时读取变量.

我的问题是,如果这是C++ 11中不推荐使用的问题,因为机器模型是多线程的,因此编译器应该考虑对系统中存在的变量的并发访问.

c++ volatile c++11

27
推荐指数
1
解决办法
1万
查看次数

"volatile"限定符和编译器重新排序

编译器无法消除或重新排序对volatile限定变量的读/写.

但是,存在其他变量的情况又volatile如何呢?

场景1

volatile int a;
volatile int b;

a = 1;
b = 2;
a = 3;
b = 4;
Run Code Online (Sandbox Code Playgroud)

编译器可以重新排序第一次和第二次,第三次和第四次分配吗?

情景2

volatile int a;
int b, c;

b = 1;
a = 1;
c = b;
a = 3;
Run Code Online (Sandbox Code Playgroud)

同样的问题,编译器可以重新排序第一个和第二个,或第三个和第四个任务吗?

c c++ volatile compiler-optimization

14
推荐指数
1
解决办法
5128
查看次数

编译器如何在 ARM 汇编中强制执行 C++ 易失性

根据 cppreference,一个volatile限定变量的存储不能重新排序为另一个volatile限定变量。换句话说,在下面的示例中,当 y 变为 20 时,可以保证 x 为 10。

volatile int x, y;
...
x = 10;
y = 20;
Run Code Online (Sandbox Code Playgroud)

根据维基百科,ARM 处理器的一个存储可以在另一个存储之后重新排序。因此,在下面的示例中,第二个存储可以在第一个存储之前执行,因为两个目的地是不相交的,因此它们可以自由地重新排序。

str     r1, [r3]
str     r2, [r3, #4]
Run Code Online (Sandbox Code Playgroud)

有了这样的理解,我写了一个玩具程序:

volatile int x, y;

int main() {
    x = 10;
    y = 20;
}
Run Code Online (Sandbox Code Playgroud)

我预计生成的程序集中会出现一些围栏,以保证 x 和 y 的存储顺序。但为 ARM生成的程序集是:

main:
        movw    r3, #:lower16:.LANCHOR0
        movt    r3, #:upper16:.LANCHOR0
        movs    r1, #10
        movs    r2, #20
        movs    r0, #0
        str     r1, [r3]
        str     r2, [r3, #4] …
Run Code Online (Sandbox Code Playgroud)

c++ assembly arm volatile memory-barriers

1
推荐指数
1
解决办法
587
查看次数