在 u8 中铸造 u16[] 时如何强制对齐错误?
How to force an alignment error when casting a u8[] in a u16?
在回答问题时,我试图警告OP注意对齐问题。
但是当我做我的片段来向 OP 展示它是如何发生的时,我无法让它发生。
在联机编译器上运行此代码 (C/C++) 时,我希望它会失败。
为什么不是呢?
#include <cstdint>
#include <cstddef>
#include <iostream>
#define SIZE 20
int main()
{
uint8_t in[20];
in[0] = 0;
in[1] = 1;//8bit
in[2] = 1;
in[3] = 1;//16bit
in[4] = 1;
in[5] = 1;
in[6] = 1;
in[7] = 1;//32bit
in[8] = 1;
in[9] = 1;
in[10] = 1;
in[11] = 1;
in[12] = 1;
in[13] = 1;
in[14] = 1;
in[15] = 1;//64bit
in[16] = 1;
in[17] = 1;
in[18] = 1;
in[19] = 1;
uint16_t out;
for (int i =0; i < SIZE - 2; i++)
{
out = *((uint16_t*)&in[i+1]);
std::cout << "&in: " << (void*)&in[i+1] << "n out: " << out << "n in: " << in[i+2]*256 + in[i+1]<< std::endl;
}
return 0;
}
运行此代码时,我希望它会失败。为什么不是呢?
因为:
- 程序的行为未定义1.不能保证失败2.
- 您可能正在使用其 CPU 支持未对齐访问的系统。据我了解,例如 x86 执行未对齐的读取和写入;它们只是比对齐的慢(但这不适用于 SIMD 指令)。
C++标准说(引用最新草案):
1
[基本.lval]
如果程序尝试通过类型与以下类型之一不相似的 glvalue ([conv.qual]) 访问对象的存储值,则行为是未定义的:
- 对象的动态类型,
- 与对象的动态类型对应的有符号或无符号类型,或
- 字符、无符号字符或 std::byte 类型。
在这种情况下,uint16_t
不是列出的异常类型(好吧,它可能在某些具有 16 位字节的系统上,但不是一般的,也可能不在运行在线编译器的服务器上,这样的系统可能不会提供uint8_t
)。
阿拉伯数字
[defns.undefined]
本文档不强加要求的行为
请注意,缺乏任何保证。
运行此代码时,我希望它会失败。为什么不是呢?
由于严格别名冲突,程序具有未定义的行为,但这并不意味着它有义务失败(请参阅"未定义")。从对齐角度来看,通过没有其目标类型的自然对齐的指针访问值必须失败,尽管这是一种主要属于严格锯齿规则保护伞的情况。 此类访问尝试是否实际失败通常取决于运行程序的硬件。
具体发生的情况取决于所使用的平台(CPU 架构和操作系统)。
有几种可能性:
-
该体系结构根本没有自然的单词对齐方式,因此所有访问都被视为对齐。
-
CPU 通过执行多个对齐的访问并构造结果(慢)在内部处理未对齐的访问。
-
CPU 检测到未对齐的访问并引发异常。操作系统捕获此异常并模拟软件中的未对齐访问(速度较慢!
例如,Linux为多个arm架构提供了此选项,甚至可以选择此选项,如果应忽略,修复或发出未对齐的访问,则可以选择它,可以选择在内核日志中伴随警告(请参阅内核源文件arch/arm/mm/alignment.c
。
- 对齐会导致 CPU 异常,并且进程发出信号。 在 Linux 上,在这种情况下,该过程通常以SIGBUS终止。
摘要:避免未对齐的访问是安全的一面,但在大多数平台上,它仍然可以以一种或另一种方式工作。
- 如何理解将半精度指针转换为无符号长指针和相关的内存对齐
- 如何创建一个QTableWidgetItem,用长文本右对齐,左边有省略号
- 我可以检测和更改 gcc/g++ 中结构的当前数据对齐设置吗?
- 64位机器上的C++内存对齐
- 为什么我可以将变量存储在不是其最小对齐方式的倍数的地址?
- 使 std::vector 分配对齐内存的现代方法
- C++ cout 将双精度对齐到精度 2 并正确对齐
- 在 64 位边界上对齐C++结构数组?
- C++ 对 32 位和 64 位处理器强制对齐的安全性
- 在 u8 中铸造 u16[] 时如何强制对齐错误?
- 警告:从 'char *' 到 'float *' 的强制转换将所需的对齐从 1 增加到 4 [-Wcast-align]
- C++将结构强制转换为 std::矢量<char>内存对齐
- 对齐方式与指针中尾随零的数量有何关系
- 是否可以强制对C中的指针参数进行内存对齐
- 如何强制对齐堆分配的对象
- 如何使用alignof强制对齐堆分配
- 在C++中强制实施内存对齐
- InterlockedCompareExchange - 确切的对齐要求是什么以及如何强制执行
- 是否可以强制GCC为内存对齐的对象生成高效的构造函数
- mmap:强制64K对齐