What does the standard say about unaligned memory access?
Asked Answered
S

1

27

I've searched through the standard about unaligned access, but didn't find anything (maybe I was inadvertent).

Is it undefined behavior? Is it implementation defined?

As a lot of current CPUs support unaligned access, it would be sensible that unaligned memory access is implementation defined. Is it the case?

By unaligned access, I mean for example:

alignas(int) char buffer[sizeof(int)+1];
int &x = *new(buffer+1) int;
x = 42;
Skilful answered 1/7, 2018 at 19:13 Comment(3)
I think the relevant section is [basic.align]. Implementation-defined.Squier
@RaymondChen: all I found is that alignment value is implementation defined. But nothing about unaligned access. Do you see something else there?Skilful
How do we know that this is an unaligned access? sizeof(int) and the required alignment are both implementation defined. Could be the same as for char.Dzoba
B
25

No, it is UB. You cannot start the lifetime of an object at unaligned memory. From [basic.life]p1

The lifetime of an object of type T begins when:

  • storage with the proper alignment and size for type T is obtained, and

  • if the object has non-vacuous initialization, its initialization is complete,

[...]

So in your example, the lifetime of the object referenced by x doesn't even begin, so any other usage of it other than mentioned in [basic.life]p6 is UB.

But what your implementation is allowed to do is say that unaligned memory (as specified by the underlying architecture used) is actually aligned, thus making your code valid under the C++ abstract machine. I'm not sure whether any compiler does this however.

Businesswoman answered 1/7, 2018 at 19:39 Comment(19)
The alignment requirement is, however, an implementation defined property.Vidrine
@MaximEgorushkin: that's true, but does it matter? Suppose that the requirement is 4. Does my example's behaviour implementation defined, or UB? Reading the quoted part, I think that Rakete1111 is right, and it is UB indeed, because new int is called on an unaligned pointer.Skilful
@MaximEgorushkin Yes it is implementation defined. But that doesn't change the fact that if that requirement is violated, no matter what it is, then you get UB, which is AFAIK exactly what OP does by adding 1.Businesswoman
@Skilful Suppose the implementation has best performance if 4-byte integers are alinged by 4-byte boundary. But it can handle unaligned access just fine. What should alignof(uint32_t) return?Vidrine
@MaximEgorushkin Whatever compiler developers decide it should return. It could return 1, or it could (as on my GCC) return 4. If hardware allows misaligned access with a performance overhead, the implementation can still return 4 to make (most) integers aligned, improving performance.Bant
@Bant You don't have to develop a compiler to return that 1. Just a back-end llvm.org/docs/WritingAnLLVMBackend.htmlVidrine
@MaximEgorushkin Here by compiler I mean an entire tool that makes object files from C++ source code.Bant
You only need to provide a definition of proper alignment now.Vidrine
@MaximEgorushkin It's probably the alignment that alignof returns.Bant
@Bant Quote the standard please.Vidrine
@MaximEgorushkin Are you trying to say that there is a possibility that alignof returns optimal rather than required alignment? The standard doesn't mention 'proper alignment' anywhere else, the closest thing I was able to find is [basic.align]/2 "The result of the alignof operator reflects the alignment requirement ...".Bant
@Businesswoman Actually, [basic.align]/2 has an interesting part in it: "The alignment required for a type might be different when it is used as the type of a complete object and when it is used as the type of a subobject. ... The result of the alignof operator reflects the alignment requirement of the type in the complete-object case." So one could say that you're allowed to access misaligned compound types under certain conditions.Bant
@HolyBlackCat: in the case of x86, it certainly returns optimal alignment, as there is no required alignment on x86 (except a few special cases). Almost all variables could use an alignment of 1, and even, there would be no significant speed loss.Skilful
@HolyBlackCat: but according to the standard, alignof means required alignment (3.11.6 of C++14). So, implementations with alignof(int)==4 give us a more strict alignment than necessary.Skilful
@Skilful At the risk of stating the obvious, an implementation is free to impose a stricter alignment requirement than the underlying hardware. Also, hardware-unaligned access has obvious issues with volatile semantics on x86 (apart from "real" hardware access, this is very relevant for sig_atomic_t).Eller
@ArneVogel: the question is then, is a memory access is UB, when the memory access is aligned from the perspective of the HW, but unaligned from the perspective of the C++ abstract machine? It seems that the answer is yes, but it is not 100% explicit in the standard.Skilful
@Skilful It is explicit. The abstract machine doesn't care about alignement of the underlying HW. If the compiler says that the memory is unaligned, then you get UB no matter the HW.Businesswoman
@Rakete1111: my only problem is that it says "proper alignment", not "required aligment" (which equals to alignof). Not a big deal, I agree with your conclusion, all I'm saying is that sentence can be improved a little bitSkilful
@Skilful I understand proper as "right", which is what alignof returns. It could be improved, I agree.Businesswoman

© 2022 - 2024 — McMap. All rights reserved.