据我所知,未对齐的访问主要意味着两件事:
- 您可能性能下降
- 您将失去对齐访问具有的加载和存储的原子性
假设性能不是问题,我想要的软件是正确的,那么未对齐的访问有多糟糕?我的理解是 x86 CPU 会正确处理此类访问,但可能需要做额外的工作来获取数据。
让我问这个问题的原因是使用 -fsanitize=undefined
编译我的代码。我收到关于未对齐的存储/负载的许多错误。我不确定这是否是一个问题,因为:
- 存储仅在单线程进程的数据准备期间执行,因此我不担心原子性的损失
- 加载是在多线程进程中执行的,其中有许多线程(四个或更多)访问数据,但数据不会被任何线程修改(保存在
const uint8_t*
变量中)
访问未对齐的原因是 const uint8_t*
数组包含来自许多不同类型的字节(uint8_t
、uint16_t
、uint32_t
、uint64_t
和 int64_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/