Aligned_alloc behaviour

Viewed 255

I have read the man of aliged_alloc and I should use it like:

void* aligned_alloc( std::size_t alignment, std::size_t size );

It returns the pointer I want to alloc with the alignment and the size.

In my code I try to use it:

int *a = aligned_alloc(1024, 10*sizeof(a));

And with

std::cout << alignof(a) << std::endl;

it gives me 8. But I expect that the results is 1024 because my alignement is 1024.

What don't I understand?

3 Answers

The alignment of a is not the alignment of the memory pointed to by a. The value of 8 given by alignof(a) is the required alignment for that type, not the largest alignment of the value of a.

When you do alignof(a), it's equivalent to doing alignof(int *), which is required to have an alignment of 8 on your compiler/machine.

The _Alignof operator (which is what the alignof macro expands to) evaluates to the alignment requirement of the type of the given operand, not what it points to (if it's a pointer).

It is evaluated at compile time, so if the operand is a pointer there's no way for it to know what it points to, if anything.

Section 6.5.3.4p3 of the C standard states:

The _Alignof operator yields the alignment requirement of its operand type. The operand is not evaluated and the result is an integer constant. When applied to an array type, the result is the alignment requirement of the element type.

Section 8.3.6 of the C++ standard states:

1 An alignof expression yields the alignment requirement of its operand type. The operand shall be a type-id representing a complete object type, or an array thereof, or a reference to one of those types.

2 The result is an integral constant of type std::size_t .

3 When alignof is applied to a reference type, the result is the alignment of the referenced type. When alignof is applied to an array type, the result is the alignment of the element type.

alignof is a static operator. It'll give you the native alignment of an object's type. alignof(a) will be native alignment of an int* pointer, and alignof(*a) will be the native alignment of an int.

aligned_alloc isn't a compile-time function. It allocates memory at runtime and the alignment of that memory will be the 2 to the count of trailing zeros in the address stored by the pointer (most easily/efficiently countable with the __builtin_ctz* builtins provided by gcc/clang).

The snippet

#include <stdlib.h>
#include <stdio.h>
#include <stdalign.h>

int main()
{
    int *a = (int*)aligned_alloc(1023,1);
    printf("%zu %zu\n", alignof(a), alignof(*a));
    printf("ctz=%u\n",__builtin_ctzll((unsigned long long)a));
    printf("%llu\n",1ull<<__builtin_ctzll((unsigned long long)a));
}

run on http://coliru.stacked-crooked.com/a/51606a7d251103a9 appears to usually return pointers aligned to 2^12 or 2^13--which is OK because such overaligned pointers are most definitely also aligned for 2^10 (==1024).

Example output:

8 4
ctz=12
4096
Related