Which guarantees does malloc make about memory alignment?
Accdording to this documentation page,
the address of a block returned by malloc or realloc in the GNU system is always a multiple of eight (or sixteen on 64-bit systems).
In general, malloc
implementations are system-specific. All of them keep some memory for their own bookkeeping (e.g. the actual length of the allocated block) in order to be able to release that memory correctly when you call free
. If you need to align to a specific boundary, use other functions, such as posix_memalign
.
The only standard rule is that the address returned by malloc
will be suitably aligned to store any kind of variable. What exactly that means is platform-specific (since alignment requirements vary from platform to platform).
The C standard says that the result of malloc()
must be cast-able to any legit pointer type. So
... = (DataType *)malloc(...);
must be possible, regardless what type DataType
is.
If a system has memory alignment requirements for certain data types, malloc()
has to take that into account. And since malloc()
cannot know to which pointer type you are going to cast the result, it always must follow the strictest memory alignment requirement.
The original wording in the standard is:
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated).
Source: ISO/IEC 9899:201x (aka ISO C11)
E.g. if a system requires int
to be 4 byte aligned and long
to be 8 byte aligned, malloc()
must return memory that is 8 byte aligned because it cannot know if you are going to cast the result to to int
or to long
.
Theoretically, if you request less than sizeof(long)
bytes, a cast to long *
is invalid as a long
would not even fit into that memory. One might think that in that case malloc()
could choose a smaller alignment but that's not what the standard says. The alignment requirement in the standard does not depend on the size of the allocation!
Since many CPUs as well as many operation system do have alignment requirements, most malloc implementation will always return aligned memory but which alignment rules it follows is system specific. There are also CPUs and systems that have no alignment requirements in which case malloc()
may as well return unaligned memory.
If you depend on a specific alignment, you can either use aligned_alloc()
, which is defined in the ISO C11 standard and thus portable to all systems for that a C11 compiler exists or you can use posix_memalign()
, which is defined in IEEE Std 1003.1-2001 (aka POSIX 2001) and is available on all POSIX conforming systems as well as systems that try to be as POSIX conforming as possible (Linux for example).
Fun fact:malloc()
on macOS always returns memory that is 16 byte aligned, despite the fact that no data type on macOS has a memory alignment requirement beyond 8. The reason for that is SSE. Some SSE instructions have a 16 byte alignment requirement and by ensuring that malloc()
always returns memory that is 16 byte aligned, Apple can very often use SSE optimization in its standard library.