是由于未定义的行为导致未对齐的载荷吗? [英] Is a misaligned load due to a cast undefined behavior?

查看:188
本文介绍了是由于未定义的行为导致未对齐的载荷吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是由于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):

指向对象类型的指针可以转换为指向不同对象类型的指针.如果生成的指针未针对所引用的类型正确对齐,则该行为是不确定的.

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(否则地址将正确对齐).

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.

这篇关于是由于未定义的行为导致未对齐的载荷吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆