c - 是否由于类型转换未定义行为导致负载未对齐?

标签 c casting undefined-behavior memory-alignment

加载未对齐是否是由于 void* 未定义行为导致的转换?


这是我对 Clang 及其 sanitizer 的观察:

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
              ^ 

这就是 Actor 发挥作用的地方:

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++;

  ...
}

相关,但我不相信回答了上面的问题:

最佳答案

向错误对齐的指针本身的转换是未定义的,不仅是通过该指针加载 (C11 (n1570) 6.3.2.3 p7):

A pointer to an object type may be converted to a pointer to a different object type. If the resulting pointer is not correctly aligned [...] for the referenced type, the behavior is undefined.

显示的代码也打破了严格的别名,因为指向的对象不太可能被声明为 uintptr_t(否则地址将正确对齐)。

为了符合标准,可以使用 unsigned char 代替。

如果出于性能原因要复制 uintptr_t 大小的 block ,可以使用 unsigned char 直到地址正确对齐,然后再循环复制 uintptr_t 。这应该通过 union 或通过 memcpy 来避免别名问题(如果大小不变,Gcc 可以优化 memcpy 调用)。可能需要再次通过 unsigned char 复制最后一个字节以避免越界访问(读取 sizeof(uintptr_t)-1 字节后的数组不应该导致问题(Glibc 在几个地方这样做),但通过 dst 写入可能会写入另一个对象)。它可能有助于限制-限定所使用的指针。

关于c - 是否由于类型转换未定义行为导致负载未对齐?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28893303/

相关文章:

c - C 中后置和前置增量运算符的奇怪行为

c - 链表段错误

c++ - 快速找到2^x的方法

如果多连接网络服务器中有一段时间不活动,则关闭套接字

c++ - 重载类型转换运算符,转换为指向函数的指针

c++ - C 样式向上转换到相同的层次级别

c++ - 什么是 "compatibility for C++ mangling"?

C++显式复制构造函数?

c - 为什么 i =++i 调用未定义的行为?

c++ - 以下是未定义的行为吗?我 = 函数(我)