Почему расширенная реализация выравнивания определена в std :: align_storage - PullRequest
0 голосов
/ 03 июня 2019

Почему поддержка расширенной реализации выравнивания определяется в std::aligned_storage_t? Должно быть довольно легко указать реализацию, которая использует alignas() для внутреннего буфера соответствующего размера?

1 Ответ

2 голосов
/ 03 июня 2019

Вся поддержка расширенного выравнивания определяется реализацией :

Определяется реализацией, поддерживаются ли какие-либо расширенные выравнивания и контексты, в которых они поддерживаются .

Добавлено выделение.

Реализация свободна для поддержки расширенных выравниваний в некоторых местах, но не в других.Возможно, будет хорошо создать объект кучи с расширенным выравниванием, но не объект стека (или как подобъект переменной стека).aligned_storage - это просто другой контекст.


, почему [расширенное выравнивание] является реализацией, определенной в некоторых контекстах, где она должна быть четко определена (например, память стека)?

Рассмотрим бремя реализации распределения кучи по сравнению с выделением стека.

Что нужно сделать компилятору для работы new OverAlignedType с распределением кучи?Pre-C ++ 17?Требуется ничего .Либо ::operator new просто так будет выделять хранилище, подходящее для этого выравнивания или неопределенных результатов поведения.Компилятор имеет нулевой контроль над этим.То же самое касается размещения - new;в этом случае пользователь должен правильно его выровнять.

C ++ 17 добавил выровненные формы operator new.Но даже тогда единственная разница в том, какая версия функции вызывается.Это довольно просто для реализации компилятором.

Теперь рассмотрим распределение в стеке.Я создаю переменную типа OverAlignedType.Хорошо, так как это будет реализовано?Очевидно, компилятор смотрит на то, где будет смещение стека в этой точке функции, основываясь на предыдущих выделениях в стеке.Тогда это -

Неверно! Почему?Поскольку выравнивание фактического адреса для того места, где начался стек в этом вызове функции, может не подходить для этого типа.Помните: для любого данного вызова функции адрес стека будет зависеть от того, каким будет текущий граф вызовов.Если ваш OverAlignedType требует 32-байтового выравнивания, а ABI требует только 16-байтового выравнивания для начала стека, очень возможно, что иногда пользователь вызывает его, когда стек будет на 32-граница байта, а иногда и 16-байтовая.

Так что вы делаете?Что ж, вам нужно выполнить некоторый код времени выполнения , чтобы посмотреть на реальный адрес стека и выровнять его там, где это необходимо.Обратите внимание, что это превращает статическое смещение во время компиляции в динамическое.Это также может повлиять на размещение каждого стекового объекта в этой функции.

Или вы можете просто запретить пользователю использовать в стеке перегруженные типы.

...