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.
aligned_* are harmful to codebases and should not be used. At a high level: Using aligned_* invokes undefined behavior (The types cannot provide storage.) The guarantees are incorrect (The standard only requires that the type be at least as large as requested but does not put an upper bound on the size.)
struct aligned_storage; (since C++11) (deprecated in C++23) Provides the nested type type , which is a trivial standard-layout type suitable for use as uninitialized storage for any object whose size is at most Len and whose alignment requirement is a divisor of Align .
In C++11 the alignof operator used to returns the alignment, in bytes of the specified type. Syntax: alignof(type) Syntax Explanation: alignof: operator returns the alignment in byte, required for instances of type, which type is either complete type, array type or a reference type.
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 toalignof(T)
for some typeT
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With