Why does allocation of std::aligned_storage always have an offset?
c++, gcc, memory-alignment
Solution
It's not quite clear how the alignment requirements transpose to storage allocated with `new`. The standard maintains in [expr.new] that
It is implementation-defined whether over-aligned types are supported (3.11).
[basic.align]/3:
An extended alignment is represented by an alignment greater than `alignof(std::max_align_t)`. It is implementation-defined whether any extended alignments are supported and the contexts in which they are supported (7.6.2). A type having an extended alignment requirement is an over-aligned type.
Over-aligned types might not be supported by GCC, and the "non-support" of this might (instead of a compiler error) lead to the allocation function only returning storage aligned with the strictest fundamental alignment: `sizeof(std::max_align_t)`. If the value of the latter is 16 on your machine, that would explain that the address is a multiple of 16.
Also note that, despite the fact that runtime allocation functions will have maximum supported alignments, `operator new` can basically not take desired alignments into account as it has no parameter that could take the corresponding value and pass it on to the runtime environments allocation function. This problem is known and subject of an EWG-issue.
Fun-fact: The above code is invoking UB. Consider the table in [meta.trans.ptr] that lists the requirements for `aligned_storage`s second template argument:
`Align` shall be equal to `alignof(T)` for some type `T` or to default-alignment.
If no type `T` has an alignment of `4096` the requirement for the template argument is not fit. And what type would have an alignment of 212?
However, this is not important to the essence of the question. We can just use `new` with an own typedef.
Problem
When allocating an `std::aligned_storage<2, 4096>::type` on the heap I always get a pointer that is offset by 16 bytes (on x64; on x86 it is offset by 8 bytes). In other words, this: ``` #include <iostream> #include <cstddef> int main() { typedef std::aligned_storage<2, 4096>::type MemPage; MemPage* p_mp = new MemPage; std::cout << (void*)p_mp << std::endl; return 0; } ``` gives me (for example) ``` 0x72f010 ``` although I would expect all the last three digits to be zero. When allocating the `std::aligned_storage<>::type` on the stack everything works as expected. I use gcc-4.8.2 x86_64 on ubuntu 14.04.