Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
867 views
in Technique[技术] by (71.8m points)

c - Is a misaligned load due to a cast undefined behavior?

Is a misaligned load due a a cast from void* undefined behavior?


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:

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.

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).

To be standard conforming, unsigned char can be used instead.

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...