Created on 2023-10-18.00:00:00 last changed 14 months ago
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.
History | |||
---|---|---|---|
Date | User | Action | Args |
2023-10-18 00:00:00 | admin | create |