Reputation: 41
malloc() documentation says that the returned pointer is suitably aligned for any kind of variable. On my system, a long double has size 12, however some pointers returned by malloc() are aligned on 8 byte boundary and not 12. (ptr % 12 gives 4). Can anybody point out what am I missing here? Thanks in advance.
Upvotes: 4
Views: 2087
Reputation: 169693
You're missing that while a type's size must be a multiple of its alignment (which is restricted by the actual hardware), they need not be equal.
In case of long double
, this translates to
_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 long double
has 80-bit extended precision.
If we were not restricted by alignment, most naturally we'd end up with
sizeof (long double) == 10
In the presence of alignment, we'd either have to go with an alignment of 2 (which we don't for efficiency reasons), or introduce padding to arrays so elements align correctly. This violates C language semantics were an array's size is the product of its element size and count.
Upvotes: 0
Reputation: 215427
On any sane cpu architecture, the largest possible alignment requirement for an object of size 12 is 4. The alignment requirement must be a power of 2 that divides the size of the type evenly. Indeed this gives very poor alignment (objects spanning cache lines or even pages!), which is why the x86_64 ABI changed the size of long double
to 16: so that it would be possible to align it not to cross any boundaries.
Upvotes: 3
Reputation:
Evidently, long double
need not be aligned to 12 bytes. On systems such as yours, the largest alignment for a primitive C type is 8 bytes for double
. Don't confuse alignment and size - while many smaller (especially primitive) types must be naturally aligned - that is, aligned to their own size - this is prohibitive for larger data types (think fragmentation) and doesn't make anything easier for the hardware.
Upvotes: 5
Reputation: 5307
malloc
will return memory properly aligned for any type, because typically the pointer it returns is converted to a pointer of an arbitrary type and such conversion is typically (read: infinitely close to 100% of the time) a no-op. For any architecture and compiler the maximum alignment of any type is however a constant and typically it is the maximum of the alignment of all primitive types. The size of an object should however 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
, similar to sizeof
, so you can check the actual alignment with a small program. I think on your architecture the maximum alignment is 4. If malloc
always returns addresses aligned by 8, then it still complies. It is not unusual for malloc
to meet an alignment that is a multiple of the maximum alignment of the types.
Upvotes: 0
Reputation: 145899
On gcc
for Linux and x86
you have:
sizeof (long double) == 12
and
on gcc
for Linux and x64
you have:
sizeof (long double) == 16
The ABI alignment requirements for x64
long double
is 16
-bytes. For x86
, no type requires more than 8
-bytes of alignment.
To respect that glibc
malloc
returns memory object aligned with 8
-bytes on 32-bit
system and aligned on 16
-bytes for 64
-bit systems.
From glibc
doc:
The block that malloc gives you is guaranteed to be aligned so that it can hold any type of data. On GNU systems, the address is always a multiple of eight on most systems, and a multiple of 16 on 64-bit systems.
Upvotes: 4