问题描述
是由于void*
未定义行为导致的转换导致的载荷未对齐?
Is a misaligned load due a a cast from void*
undefined behavior?
这是我在使用Clang及其消毒剂时看到的内容:
Here's what I am seeing with Clang and its sanitizers:
bufhelp.h:146:29: runtime error: load of misaligned address 0x7fff04fdd0e1 for type 'const uintptr_t' (aka 'const unsigned long'), which requires 8 byte alignment
0x7fff04fdd0e1: note: pointer points here
00 00 00 66 66 6f 6f 62 61 72 34 32 46 4f 4f 42 41 52 31 37 66 6f 6f 62 61 72 34 33 46 4f 4f 42
^
这是演员阵容发挥作用的地方:
And here's where the cast comes into play:
buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
{
...
ldst = (uintptr_t *)(void *)dst;
lsrc1 = (const uintptr_t *)(const void *)src1;
lsrc2 = (const uintptr_t *)(const void *)src2;
for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t))
*ldst++ = *lsrc1++ ^ *lsrc2++;
...
}
相关,但我不相信能回答上面的问题:
Related, but I don't believe answers the question above:
- What is a misaligned pointer?
- Type punning and Unions in C
- Type punning with void * without breaking the strict aliasing rule in C99
推荐答案
转换为错误对齐的指针本身是不确定的,不仅是通过该指针的加载(C11(n1570)6.3.2.3 p7):
The conversion to a wrongly aligned pointer itself is undefined, not only a load through that pointer (C11 (n1570) 6.3.2.3 p7):
所显示的代码也打破了严格的别名,因为指向的对象不太可能声明为uintptr_t
(否则地址将正确对齐).
The code shown also breaks strict aliasing, as the pointed-to object is unlikely to be declared as uintptr_t
(the address would be correctly aligned otherwise).
要符合标准,可以使用unsigned char
.
To be standard conforming, unsigned char
can be used instead.
如果出于性能原因应复制uintptr_t
大小的块,则可以使用unsigned char
,直到地址正确对齐为止,然后再进行一次循环复制uintptr_t
.这应该通过并集或通过memcpy
来完成,以避免混叠问题(如果大小恒定,Gcc可以优化memcpy
调用).可能需要再次通过unsigned char
复制最后一个字节,以避免越界访问(从数组读取的sizeof(uintptr_t)-1
字节应该不会引起问题(Glibc在多个地方都这样做),但是通过dst
可能会写入另一个对象).可能有助于restrict
限定所使用的指针.
If uintptr_t
-sized chunks shall be copied for performance reasons, unsigned char
can be used until the address is properly aligned, followed by another loop copying uintptr_t
. This should be done through a union or via memcpy
to avoid aliasing issues (Gcc can optimize memcpy
calls out if the size is constant). The last bytes may need to be copied via unsigned char
again to avoid out-of-bounds access (a read sizeof(uintptr_t)-1
bytes past the array shouldn't cause problems (Glibc does this in several places), but the write through dst
may write into another object). It may help to restrict
-qualify the pointers used.
这篇关于是由于未定义的行为导致未对齐的载荷吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!