From 5.3.5 [expr.delete] in n3242:
2
[...]
In the second alternative (delete
array), the value of the operand of
delete may be a null pointer value or
a pointer value that resulted from a
previous array new-expression. If
not, the behavior is undefined. [...]
which means that for delete[] p
, p
must have been the result of something of the form new[] p
(a new expression), or 0. Seeing as the result of operator new
is not listed here, I think the first case is right out.
I believe the second case is Ok.
From 18.6.1.2 [new.delete.array]:
11
void operator delete[](void* ptr) noexcept;
[...]
Requires: ptr shall be a null pointer
or its value shall be the value
returned by an earlier call to
operator new or
operator new[](std::size_t,const
std::nothrow_t&) which has not been
invalidated by an intervening call to
operator delete. [...]
(there is similar text in 3.7.4.2 [basic.stc.dynamic.deallocation], paragraph 3)
So as long as the de/allocation functions match (e.g. delete[] (new[3] T)
is well-formed) nothing bad happens. [ or does it? see below ]
I think I tracked the normative text of what Jerry is warning about, in 5.3.4 [expr.new]:
10
A new-expression passes the amount of
space requested to the allocation
function as the first argument of type
std::size_t. That argument shall be no
less than the size of the object being
created; it may be greater than the
size of the object being created only
if the object is an array. [...]
Following in the same paragraph is an example (so non-normative) which underlines that the new expressions of an implementation are indeed free to ask more from the allocation function than the space the array takes (storing the optional std::size_t
parameter available to deallocation function comes to mind), and that they can offset into the result. So all bets are off in the array case. The non-array case seems fine though:
auto* p = new T;
// Still icky
p->~T();
operator delete(p);