web-dev-qa-db-ja.com

gccの過剰調整された新しいサポート(alignas)

GCCのaligned-new警告とgcc -faligned-newオプションに関する詳細情報を見つけるのが困難です。 gcc 7.2.0(--std = c ++ 17なし)でコンパイルし、次のような境界整列構造体を定義しようとします。

_struct alignas(64) Foo { int x; }
_

単純な古いことをするだけです:

_Foo * f = new Foo();
_

次の警告と提案をします。

_ 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
_

デフォルトではnewalignof( std::max_align_t )(これは16です)までのメモリのみを返すことを理解していますが、-faligned-newを渡した場合、 gccは、代わりにnewの適切な新しい配置を強制しますか?

残念ながら、これに関するgccのドキュメントは非常に不足しています。

9
ByteMe95

gcc's manual から:

-faligned-new
_void* ::operator new(std::size_t)が提供するよりも多くのアライメントを必要とするタイプのC++ 17 newのサポートを有効にします。 -faligned-new = 32などの数値引数を使用して、その関数によって提供されるアライメント(バイト単位)の量を指定できますが、alignof(std::max_align_t)のデフォルトをオーバーライドする必要があるユーザーはほとんどいません。

これは、-faligned-newが P0035R4 に追加されたaligned-new機能を、C++ 17サポートを完全に有効にしなくても利用できるようにすることを意味します。

C++標準からの関連ビット:
[cpp.predefined]から:

___STDCPP_DEFAULT_NEW_ALIGNMENT___
値がoperator new(std::size_t)またはoperator new[](std::size_t)の呼び出しによって保証されるアラインメントである_std::size_t_タイプの整数リテラル。 [注:より大きいアライメントはoperator new(std::size_t, std::align_val_t)などに渡されます(8.3.4)。 —エンドノート]

[basic.align/3]から:

新しい拡張アラインメントは、___STDCPP_DEFAULT_NEW_ALIGNMENT___より大きいアラインメントで表されます

そして[expr.new/14]から:

オーバーロードの解決は、引数リストを組み立てることによって作成された関数呼び出しで実行されます。最初の引数は要求されたスペースの量であり、タイプは_std::size_t_です。割り当てられたオブジェクトの型が新しく拡張された配置を持つ場合、次の引数は型の配置であり、型は_std::align_val_t_です。


したがって、C++ 17または-faligned-newの場合、Fooにはnew-extended alignmentFoo* f = new Foo();void* operator new(size_t, align_val_t)を呼び出してメモリを割り当て、64バイト境界に適切に配置されたFooオブジェクトへのポインターを返します。以前の基準ではそうではありませんでした。

7
Miles Budnek