Malloc and unaligned memory

Documentation

malloc () states that the returned pointer is properly aligned for any variable. On my system, the long double size is 12, however some of the pointers returned by malloc () are aligned on an 8-byte boundary, not 12. (ptr% 12 gives 4). Can anyone point out what I'm missing here? Thanks in advance.

+4
source share
5 answers

Obviously, long double does not need to be aligned with 12 bytes. On systems like yours, the largest alignment for primitive type C is 8 bytes for double . Do not confuse alignment and size - while many smaller (especially primitive) types should be naturally aligned, that is, aligned in size - this is forbidden for large data types (I think fragmentation) and does not make anything easier for the hardware.

+5
source

In gcc for Linux and x86 you have:

sizeof (long double) == 12

and

on gcc for Linux and x64 you have:

sizeof (long double) == 16

ABI alignment requirements for x64 long double are 16 -bytes. For x86 , the type does not require more than 8 bytes of alignment.

Regards, glibc malloc returns a memory object aligned with 8 bytes in a 32-bit and aligned with 16 bytes for 64 bit systems.

From glibc doc:

The block that malloc gives you must be aligned so that it can store any type of data. On GNU systems, on most systems, the address is always a multiple of eight, and on 64-bit systems it is 16.

+3
source

In any cpu system architecture, the largest possible alignment requirement for an object of size 12 is 4. The alignment requirement must be a power of 2, which evenly divides the type size. This is actually a very poor alignment (objects that span cache lines or even pages!), So x86_64 ABI resized the long double to 16: so that it can be aligned so as not to cross borders.

+3
source

malloc returns the correct aligned memory for any type, because usually the pointer it returns is converted to a pointer of any type, and such a conversion is usually (read: infinitely close to 100% of the time) op. For any architecture and compiler, the maximum alignment of any type, however, is constant and is usually the maximum alignment of all primitive types. However, the size of the object must be a multiple of its alignment. Sometimes this requirement must be met by adding padding to the value inside the object.

If your compiler is modern enough, it will support _Alignof , like sizeof , so you can check the actual alignment with a small program. I think that in your architecture the maximum alignment is 4. If malloc always returns addresses aligned to 8, then it still respects. It is not unusual for malloc to perform an alignment that is a multiple of the maximum type alignment.

0
source

You are missing the fact that the font size should be a multiple of its alignment (limited by the actual equipment), they should not be equal.

In the case of long double this means

 _Alignof (long double) == 4 sizeof (long double) == 12 

with gcc / x86 and

 _Alignof (long double) == 16 sizeof (long double) == 16 

with gcc / x64, where in both cases the long double has 80-bit extended precision.

If we were not limited to alignment, then naturally we ended up with

 sizeof (long double) == 10 

If there is alignment, we must either go with alignment 2 (which is not for reasons of efficiency), or introduce an addition to arrays so that the elements align correctly. This violates the semantics of the C language, since the size of the array is a product of its size and the number of elements.

0
source

Source: https://habr.com/ru/post/1488855/


All Articles