C 未对准的负载是否由未定义的铸造行为引起?
是否由于未定义的行为造成的铸造导致荷载未对准C 未对准的负载是否由未定义的铸造行为引起?,c,casting,undefined-behavior,memory-alignment,C,Casting,Undefined Behavior,Memory Alignment,是否由于未定义的行为造成的铸造导致荷载未对准 以下是我在Clang及其消毒剂中看到的情况: 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 her
以下是我在Clang及其消毒剂中看到的情况:
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
^
这里是演员们发挥作用的地方:
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++;
...
}
相关,但我不相信上述问题的答案:
最后一个个人意见是,由于您的buf_xor()实现需要在某些处理器/编译器实现上使用对齐指针作为参数,因此您可以通过更改签名来反映这一点(将void*更改为uintptpr_t*)——或者更改实现本身来优雅地处理,从而避免将来的一些麻烦,“手动”,所有架构上的地址都未对齐。到错误对齐指针的转换本身未定义,而不仅仅是通过该指针的加载(C11(n1570)6.3.2.3 p7): 指向对象类型的指针可以转换为指向不同对象类型的指针。如果所引用类型的结果指针未正确对齐[…],则行为未定义 显示的代码也打破了严格的别名,因为指向的对象不太可能声明为
uintpttr\u t
(否则地址将正确对齐)
为了符合标准,可以使用无符号字符
如果出于性能原因,应复制
uintpttr\u t
-大小的块,则可以使用无符号字符
,直到地址正确对齐,然后再进行另一个循环复制uintptpr\u t
。这应该通过联合或通过memcpy
来完成,以避免混淆问题(如果大小不变,Gcc可以优化memcpy
调用)。最后的字节可能需要再次通过无符号字符
进行复制,以避免越界访问(读取sizeof(uintptpr_\t)-1
字节超过数组不会导致问题(Glibc在多个位置执行此操作),但直写dst
可能会写入另一个对象)。它可能有助于限制使用的指针。这实际上是我正在分析和验收测试的GnuPG代码。我想解决调用方中的联合或对齐指针的问题。但是它在很多地方都完成了,因此使用memcpy
将函数修复为临时函数变得更加容易。不过,我会将错误报告归档以提醒他们注意这个问题(请参阅)。这完全取决于您在该函数中显示的参数。如果看不到调用代码,就不可能回答这个问题。@Lundin-是这样吗?Clang已通知地址为0x7fff04fdd0e1。0xxxxxxx1
是否曾经是循环中使用的uintpttr\u t*
?或者我分析Clang的输出不正确?是的,但为什么是XXX1?必须向函数传递字符指针或其他内容。发布的代码中没有任何内容会导致未对齐,因为您在那里执行的所有指针算法都基于正确的类型。编辑了越界访问部分。在我喝第一杯咖啡之前,我不应该建议忽视UB。。。