I'm having some difficulty finding more information about GCC's aligned-new warning and the gcc -faligned-new option. Compiling on gcc 7.2.0 (without --std=c++17) and trying to define an aligned struct such as:
struct alignas(64) Foo { int x; }
Just doing a plain old:
Foo * f = new Foo();
Gives me the following warning and suggestion:
alignas.cpp:36:25: warning: ‘new’ of type ‘Foo’ with extended alignment 64 [-Waligned-new=]
Foo * f = new Foo();
^
alignas.cpp:36:25: note: uses ‘void* operator new(long unsigned int)’, which does not have an alignment parameter
alignas.cpp:36:25: note: use ‘-faligned-new’ to enable C++17 over-aligned new support
I understand that by default new
will only return memory aligned up to alignof( std::max_align_t )
( which is 16 for me ), but what's not clear to me is that if I pass -faligned-new, will gcc now enforce proper new alignment of new
on my behalf?
Unfortunately the gcc documentation on this is extremely lacking.
Unfortunately the gcc documentation on this is extremely lacking. Enable support for C++17 new of types that require more alignment than void* ::operator new (std::size_t) provides.
A new-extended alignment is represented by an alignment greater than __STDCPP_DEFAULT_NEW_ALIGNMENT__ Overload resolution is performed on a function call created by assembling an argument list. The first argument is the amount of space requested, and has type std::size_t.
Support for /Zc:alignedNew is available starting in Visual Studio 2017 version 15.5. This sample shows how operator new and operator delete behave when the /Zc:alignedNew option is set. This output is typical for 32-bit builds. The pointer values vary based on where your application runs in memory.
To set this compiler option in the Visual Studio development environment Open the project's Property Pages dialog box. Select the Configuration Properties > C/C++ > Command Line property page. Modify the Additional Options property to include /Zc:alignedNew or /Zc:alignedNew- and then choose OK.
From gcc's manual:
-faligned-new
Enable support for C++17new
of types that require more alignment thanvoid* ::operator new(std::size_t)
provides. A numeric argument such as -faligned-new=32 can be used to specify how much alignment (in bytes) is provided by that function, but few users will need to override the default ofalignof(std::max_align_t)
.
This implies that -faligned-new simply makes the aligned-new features added in P0035R4 available without fully enabling C++17 support.
The relevant bits from the C++ standard:
From [cpp.predefined]:
__STDCPP_DEFAULT_NEW_ALIGNMENT__
An integer literal of typestd::size_t
whose value is the alignment guaranteed by a call tooperator new(std::size_t)
oroperator new[](std::size_t)
. [ Note: Larger alignments will be passed tooperator new(std::size_t, std::align_val_t)
, etc. (8.3.4). — end note ]
From [basic.align/3]:
A new-extended alignment is represented by an alignment greater than
__STDCPP_DEFAULT_NEW_ALIGNMENT__
And from [expr.new/14]:
Overload resolution is performed on a function call created by assembling an argument list. The first argument is the amount of space requested, and has type
std::size_t
. If the type of the allocated object has new-extended alignment, the next argument is the type’s alignment, and has typestd::align_val_t
.
So in your case with C++17 or -faligned-new, since Foo
has new-extended alignment, Foo* f = new Foo();
will call void* operator new(size_t, align_val_t)
to allocate memory and return a pointer to a Foo
object that is properly aligned on a 64-byte boundary. Under earlier standards that was not the case.
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