Placment new с невыровненной памятью даёт UB.
Как я понимаю, формально мы сталкиваемся с двумя пунктами стандарта:
8.5.2.4 пункт 17
When the allocation function returns a value other than null, it must be a pointer to a block of
storage in which space for the object has been reserved. The block of storage is assumed to be appropriately
aligned and of the requested size.
и
21.6.2.3 Non-allocating forms
operator new and operator delete.
[[nodiscard]] void operator new(std::size_t size, void ptr) noexcept;
Returns: ptr.
Remarks: Intentionally performs no other action.
Т.е. при placement new ответственность за выравнивание лежит на вызывающем коде и никто не проверяет, что память выровнена.
Остаётся понять, когда же это приводит к чему-то плохому. Возьмём какой-нибудь тип, для которого выравнивание важно, например, __m128i. Готово! Можно падать.
Минимальный рабочий пример:
https://godbolt.org/z/PxeqjqGhd
Замена buffer+1 на buffer в примере убирает segfault.
Placment new с невыровненной памятью даёт UB. Как я понимаю, формально мы сталкиваемся с двумя пунктами стандарта:
8.5.2.4 пункт 17
и 21.6.2.3 Non-allocating forms
Т.е. при placement new ответственность за выравнивание лежит на вызывающем коде и никто не проверяет, что память выровнена. Остаётся понять, когда же это приводит к чему-то плохому. Возьмём какой-нибудь тип, для которого выравнивание важно, например,
__m128i
. Готово! Можно падать. Минимальный рабочий пример: https://godbolt.org/z/PxeqjqGhdЗамена
buffer+1
наbuffer
в примере убирает segfault.