C++易失性:保证 32 位访问?

C++ volatile: guaranteed 32-bit accesses?

本文关键字:访问 保证 易失性 C++      更新时间:2023-10-16

在我的Linux C++ 项目中,我在物理地址空间的某个地方映射了一个硬件内存区域,在执行mmap后,我使用uint32_t指针访问该区域。

应用程序的发布版本崩溃并显示SIGBUS(总线错误(。

发生这种情况是因为编译器使用 64位访问优化对上述硬件内存的访问,而不是坚持 32 位 => 总线错误,只能使用 32 位读/写访问硬件内存

我将uint32_t指针标记为易失性

它有效。至少对于这一个特定的代码部分。因为编译器被告知不要进行重新排序。大多数时候,它必须重新排序才能优化。

我知道编译器何时访问内存易失性控制。问题是:易失性是否也告诉编译器如何访问内存,即完全按照程序员的指示访问内存我是否保证编译器将始终坚持对易失性uint32_t缓冲区进行 32 位访问?

例如,易失性是否还保证编译器也将使用 32 位读/写访问以下代码片段中 2 次连续写入 2 次连续的 32 位值

void aFunction(volatile uint32_t* hwmem_array)
{
[...]
// Are we guaranteed by volatile that the following 2 consecutive writes, in consecutive memory regions
// are not merged into a single 64-bit write by the compiler?
hwmem_array[0] = 0x11223344u;
hwmem_array[1] = 0xaabbccddu;
[...]
}

我想我回答了我自己的问题,如果我错了,请纠正我。

C99标准草案:http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf

引号:

">

6 具有可变限定类型的对象可以通过以下方式进行修改 实现未知或有其他未知的副作用。 因此,任何提及此类对象的表达都应是严格按照抽象机器的规则进行评估,如 在 5.1.2.3 中描述。此外,在每个序列点的值 最后存储在对象中应符合规定的 抽象机器,除非被提到的未知因素修改 以前。

">

第 5.1.2.3 节:

">

2访问易失性对象,修改对象,修改文件, 或者调用执行任何这些操作的函数都是 side 效果,即执行环境状态的更改。评估表达式可能会产生副作用。在某些时候 执行序列中的指定点称为序列点全部 先前评估的副作用应完整且无侧面 后续评价的效果应已发生。(摘要 的序列点见附件C。

5 对符合性实施的最低要求是: — 在 序列点,易失性对象稳定的,因为以前的访问是完整的,后续访问尚未完成 发生了

">

附件C(信息性(序点:

">

1

以下是 5.1.2.3 中描述的序列点:

[...]

完整表达式的结尾:初始值设定项 (6.7.8(; 表达式 在表达式语句 (6.8.3( 中;的控制表达式 选择语句(如果或开关((6.8.4(;控制表达式 一段时间或做声明(6.8.5(;对于的每个表达式 声明(6.8.5.3(;返回语句 (6.8.6.4( 中的表达式。

">

因此,从理论上讲,我们可以保证,在任何涉及易失性的对象的表达式结束时,易失性对象被写入/读取,正如编译器被指示的那样