- 主题:reinterpret_cast<uint *>(void *) 碰到未对齐内存会出错吗?
单纯的cast肯定不会报错,只是deref时可能触发系统异常。也就是语言或者编译器无要求,只是硬件/os的要求。
x86是没问题的(只是默认情况下。有寄存器开关的),随便align。
windows下只有kerner driver或者少数的API对于传入的mem有align要求。API的align要求一般也是下层的kernel driver或者硬件引起的。不过这个传参的align和deref的align有差异。
SEM_NOALIGNMENTFAULTEXCEPT
https://docs.microsoft.com/en-us/windows/win32/api/errhandlingapi/nf-errhandlingapi-seterrormode
ARM老版本之类的可能有问题
https://stackoverflow.com/questions/32062894/take-advantage-of-arm-unaligned-memory-access-while-writing-clean-c-code
已经式微/消失的SPARC也有align要求
https://docs.oracle.com/cd/E23824_01/html/819-3196/hwovr-1.html
【 在 Akyrum 的大作中提到: 】
: 我一直这么用,网卡、usb、pcie收到的数据转float*、double*、__m256*直接用没报错
--
修改:z16166 FROM 114.241.227.*
FROM 114.241.227.*
手册能查到。x86(包括x64)的对齐检查通过下面三个东西控制是否启用:
1、CR0寄存器的AM位(Alignment mask)。ring 0才能修改这个位。要测试必须写个kernel module。
2、EFLAGS寄存器的AC位(Alignment check)。ring 3就能修改这个位。
3、当前处于ring 3。
linux和windows对此的处理也可能不一样。windows允许通过SetErrorMode()选择是否让os把对齐异常抛给app自己处理。
【 在 stub 的大作中提到: 】
: 别的不知道,x86前两天刚试过,是这样的
--
FROM 114.241.227.*
那是肯定的
MS以前有个老帖子,论述比较清楚,而且有性能对比测试的现成代码,MS自家居然给删了
幸好有人mirror了
Windows Data Alignment on IPF, x86, and x86-64
https://blog.csdn.net/zade/article/details/549411
【 在 Akyrum 的大作中提到: 】
: 对齐运算速度是快些,而我以前拿gromacs里一些函数测了测,{copy至对齐+后续运算}耗时比{_mm256_loadu+后续运算}长百分之几~十。所以我习惯不对齐直接拿来算
: :
--
FROM 114.241.227.*
咬文嚼字一下。感觉啃pdf有点无聊了
一、
void比较特殊,是个incomplete type,而且不能成为complete type。
incomplete type没有"对齐要求"这一说法,所以printf("%u", alignof(void))这样的编译不过去。
C++ 17的"8.2.10 Reinterpret cast"这一节明确说了,只有满足这一节的第2到第11条的,才能显式使用reinterpret_cast。
不满足这几条的,到底是forbidden,还是unspecified behaviour,还是undefined behaviour,没明说。
由于void没有对齐的说法,所以reinterpret_cast<uint *>(void *)是不满足上述第2到第11条的。
而reinterpret_cast<short *>(int *)这种可以认为满足第7条,是OK的。
二、
static_cast是8.2.9节描述的,这一节的第13条对"void *"转换成"T *"有明确描述,如果不满足T的对齐要求,转换结果是unspecified。
三、
访问指针指向的内存,在"6.10 Lvalues and rvalues"这一节对glvalue的访问有描述。
第8条规定了8种情况,不符合这8种情况的,都属于undefined。
https://github.com/SuperCV/Book/blob/master/CXX/ISOIEC-14882-2017.pdf
【 在 hgoldfish 的大作中提到: 】
: 也就是说,从 c/cpp 标准看。。直接
: int64 load_int64(void *src) {
: return *static_cast<int*>(src);
: ...................
--
修改:z16166 FROM 114.241.227.*
FROM 114.241.227.*