c++ - C++ 中未对齐访问的正确性

标签 c++ memory undefined-behavior memory-alignment

据我所知,未对齐的访问主要意味着两件事:

  1. 可能性能下降
  2. 失去对齐访问具有的加载和存储的原子性

假设性能不是问题,我想要的软件是正确的,那么未对齐的访问有多糟糕?我的理解是 x86 CPU 会正确处理此类访问,但可能需要做额外的工作来获取数据。

让我问这个问题的原因是使用 -fsanitize=undefined 编译我的代码。我收到关于未对齐的存储/负载的许多错误。我不确定这是否是一个问题,因为:

  1. 存储仅在单线程进程的数据准备期间执行,因此我不担心原子性的损失
  2. 加载是在多线程进程中执行的,其中有许多线程(四个或更多)访问数据,但数据不会被任何线程修改(保存在 const uint8_t* 变量中)

访问未对齐的原因是 const uint8_t* 数组包含来自许多不同类型的字节(uint8_tuint16_tuint32_tuint64_tint64_t)。

我确信没有负载超出分配的 uint8_t 数组的范围(例如,程序从不从指向最后一个、两个、或分配的内存块的三个字节),并确保我的访问都是正确的 - 只是未对齐。

我读到的另一件事是,此类加载可能违反了严格的别名规则,但代码编译时没有使用 -Wstrict-aliasing -Werror(我很久以前就已启用)发出警告。

我应该填充 uint8_t 数组中的数据以确保访问对齐,还是我可以安全地忽略警告?

最佳答案

有些平台不支持未对齐的访问(您会遇到崩溃)。并且,有些平台支持未对齐访问,但有些 asm 指令需要对齐访问。比如ARM上有LDRD指令,需要对齐内存地址。不幸的是,编译器可以随意使用这条指令。但是,通常会有一个编译器扩展告诉编译器指针未对齐,因此它不会使用 LDRD。

在支持UA的平台上,有你说的惩罚。

我推荐你使用 memcpy。它适用于所有平台,现在编译器可以很好地优化它(所以你不会得到 memcpy 调用,而是快速的 mov 指令)。

关于c++ - C++ 中未对齐访问的正确性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44745953/

相关文章:

c++ - 在 C++ 中记录动态数据

ios - 在 iOS 中预分配内存

c++ - 什么标准对临时继承人进行静态转换?

c++ - 这种类型的双关语定义明确吗?

javascript - 什么在吞噬我的内存? (SAW、JS内存使用版)

c++ - 在编译时填充 std::array 和 const_cast 可能的未定义行为

c++ - 嵌套类中的构造函数 (C++)

c++ - 在 C++ 中循环遍历字符串 vector 的字符串元素中的所有字符

c++ - 使用不同/未知类型的类模板初始化 vector

VS2010 中的 JavaScript Intellisense 速度极慢且内存不足