gcc выровнял новую поддержку (alignas)

У меня возникают трудности с поиском дополнительной информации о выровненном новом предупреждении GCC и опции 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

Я так понимаю по умолчанию new вернет только память, выровненную до alignof( std::max_align_t ) (для меня это 16), но что мне не ясно, так это то, что если я передам -faligned-new, gcc теперь принудительно установит правильное новое выравнивание new от моего имени?

К сожалению, документации gcc по этому вопросу крайне не хватает.

6

Решение

От Руководство GCC:

-faligned новый
Включить поддержку C ++ 17 new типов, которые требуют большего выравнивания, чем void* ::operator new(std::size_t) обеспечивает. Числовой аргумент, такой как -faligned-new = 32, можно использовать, чтобы указать, сколько выравнивания (в байтах) предоставляется этой функцией, но немногим пользователям потребуется переопределить значение по умолчанию для alignof(std::max_align_t),

Это означает, что -faligned-new просто делает добавленные новые функции в P0035R4 доступно без полной поддержки C ++ 17.

Соответствующие биты из стандарта C ++:
Из [cpp.predefined]:

__STDCPP_DEFAULT_NEW_ALIGNMENT__
Целочисленный литерал типа std::size_t значение которого является выравниванием, гарантированным вызовом operator new(std::size_t) или же operator new[](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 имеет новое расширенное выравнивание, Foo* f = new Foo(); позвоню void* operator new(size_t, align_val_t) выделить память и вернуть указатель на Foo объект, который правильно выровнен на границе 64 байта. По более ранним стандартам это было не так.

3

Другие решения

Других решений пока нет …