C++易失性:保证 32 位访问?
C++ volatile: guaranteed 32-bit accesses?
在我的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( 中的表达式。
">
因此,从理论上讲,我们可以保证,在任何涉及易失性的对象的表达式结束时,易失性对象被写入/读取,正如编译器被指示的那样。
- 通过方法访问结构
- 使用不带参数的函数访问结构元素
- 如果我只是不访问queue_front节点的子节点,而是将它们推到队列中呢?还是BFS吗
- 用于访问容器<T>数据成员的正确 API
- 访问者访问变体并返回不同类型时出错
- 尝试通过多个向量访问变量时,向量下标超出范围
- 无法访问嵌套类.类的使用无效
- 与互斥锁相比,旋转锁可以保证上下文切换
- 写入位置0x0000000C时发生访问冲突
- 我们可以访问一个不存在的联盟的成员吗
- C++从另一个类访问公共静态向量的正确方法是什么
- 我的简单if-else语句是如何无法访问的代码
- 从C++dll访问C#中的一行主要参数
- C++ 11 中的锁定是否保证访问数据的新鲜度?
- C++易失性:保证 32 位访问?
- 我可以保证以负偏移访问指针吗?
- gcc是否保证对volatile整数的对齐访问是原子访问
- 是否有任何关于带有UB的代码应该是可访问的保证
- 类结构保证是访问顺序
- 给一个c++类foo,里面有一个同步方法.如何保证同步方法只能被一个线程访问