写入内存是否为可观察的行为

Is writing to memory an observable behaviour?

本文关键字:观察 内存 是否      更新时间:2023-10-16

我看过标准,但没有发现任何迹象表明,简单地写入内存将被视为可观察的行为。如果不是,则意味着编译后的代码实际上不需要写入该内存。如果编译器选择优化这种访问,任何涉及映射器内存或共享内存的东西都可能无法工作。

1.9-8似乎定义了一个非常有限的可观察行为,但表明实现可以定义更多。可以假设任何高质量的编译器会把修改内存作为一种可观察的行为吗?也就是说,它可能不能保证原子性或排序,但可以保证数据最终会被写入。

那么,我是否忽略了标准中的某些内容,或者仅仅是编译器决定要做的事情?

来自当前或c++ 0x标准的

语句很好。请注意,我不是在谈论通过函数访问内存,我的意思是直接访问,例如将数据写入指针(可能通过mmap或其他库函数检索)。

这就是volatile存在的意义。否则,写入内存而从未明显地从内存中读取是不可观察的行为。然而,在一般情况下,优化器几乎不可能证明您从未回读它,除非在相对较小的示例中,所以这通常不是问题。

可以假设任何高质量的编译器都会将修改内存视为可观察的行为吗?

。Volatile就是用来标记它的。但是,即使在添加了volatile限定符之后,也不能完全信任编译器,至少2008年的一篇论文是这样说的:http://www.cs.utah.edu/~regehr/papers/emsoft08-preprint.pdf

编辑:

源自C标准(非c++) http://c0x.coding-guidelines.com/5.1.2.3.html

如果可以推断出表达式的值没有被使用,并且没有产生必要的副作用(包括调用函数或访问易失性对象所引起的任何副作用),则实际实现不需要计算表达式的部分。

我对C99的理解是,除非您指定volatile,否则如何以及何时实际访问变量是实现定义的。如果指定volatile限定符,则代码必须按照抽象机的规则工作。

标准中相关部分为:6.7.3 Type qualifiers (volatile描述)和5.1.2.3 Program execution (抽象机器定义)。

一段时间以来,我知道许多编译器实际上有启发式来检测何时应该重新读取变量以及何时可以使用缓存副本。Volatile使编译器清楚地知道,对变量的每次访问实际上都应该是对内存的访问。没有volatile,编译器似乎永远不会重新读取变量。

顺便说一句,在函数中包装访问并不会改变这一点,因为即使没有内联的函数仍然可能被编译器内联在当前编译单元内。

从你下面的问题:

假设我在堆上使用一个数组(未指定分配的位置),我用这个数组来执行一个计算(临时空间)。的Optimizer看到它实际上不需要任何空间能严格使用寄存器。编译器还是会写内存的临时值?

不能保证,也不太可能。考虑一个静态单分配的优化器。这计算出每个可能的写/读依赖,然后分配寄存器来优化这些依赖项。作为副作用,任何写操作之后没有(可能的)读操作不创建任何依赖项,并被消除。在你的例子中("严格使用寄存器")优化器已经满足了所有的写/读与寄存器的依赖关系,因此它根本不会写入内存。所有读取产生正确的值,所以这是一个正确的优化。