This is an unofficial snapshot of the ISO/IEC JTC1 SC22 WG21 Core Issues List revision 115g. See http://www.open-std.org/jtc1/sc22/wg21/ for the official list.

2024-12-16


2812. Allocation with explicit alignment

Section: 7.6.2.8  [expr.new]     Status: open     Submitter: Tim Song     Date: 2023-10-18

Consider:

  #include <new>
  auto p = new (std::align_val_t{64}) T;

Is this example well-formed for T = int? This invokes the allocation function

  ::operator new(size_t, align_val_t);

If this is considered a "placement allocation function", the code is ill-formed per 7.6.2.8 [expr.new] paragraph 28, because deallocation function lookup finds a usual deallocation function. If this is considered a "usual allocation function", the rules find ::operator delete(void*) as the corresponding deallocation function.

There is implementation divergence: MSVC rejects; clang and gcc accept, but invoke ::operator delete(void*, align_val_t) if the constructor exits via an exception.

If T is a type with new-extended alignment, the preferred allocation function is operator new(std::size_t, std::align_val_t, std::align_val_t) or, as a fallback, operator new(std::size_t, std::align_val_t), removing the alignment information of T (7.6.2.8 [expr.new] paragraph 19).

As another concern, subclause 17.6.3.2 [new.delete.single] paragraph 11 disallows mixing aligned and unaligned allocation/deallocation functions, and implementations rely on that precondition. Thus, it is impossible to deallocate the memory obtained in the example using a delete-expression; an explicit deallocation function call appears to be required.

Possible resolution:

Disallow invocation of one of the allocation functions specified in 17.6.3.2 [new.delete.single] and 17.6.3.3 [new.delete.array] if the new-placement syntax is used with anything but a single expression of type std::nothrow_t.

Alternatively, make this conditionally-supported to offer a richer feature set on platforms where mixing aligned and unaligned allocation/deallocation works.