Section: 17.6 [support.dynamic], 17.6.3.2 [new.delete.single], 17.6.3.3 [new.delete.array] Status: C++17 Submitter: Richard Smith Opened: 2014-11-23 Last modified: 2017-07-30
Priority: 2
View all other issues in [support.dynamic].
View all issues with C++17 status.
Discussion:
N3778 added the following sized deallocation signatures to the library:
void operator delete(void* ptr, std::size_t size) noexcept; void operator delete[](void* ptr, std::size_t size) noexcept; void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept; void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept;
The former two are an essential part of the proposal. The latter two seem
spurious — they are not called when new (std::nothrow) X
fails due to
X::X()
throwing, because the core language rules for selecting a placement
deallocation function do not consider passing a size
argument. Instead, the
above would be the matching deallocation functions for:
void *operator new(std::size_t size, std::size_t size_again, const std::nothrow_t&) noexcept; void *operator new[](std::size_t size, std::size_t size_again, const std::nothrow_t&) noexcept;
... which don't exist.
Since they're not implicitly called, the only other possible use for those functions would be to perform an explicitly non-throwing deallocation. But... the first two overloads are already explicitly non-throwing and are required to be semantically identical to the second two. So there's no point in making an explicit call to the second pair of functions either. It seems to me that we should remove the(void*, size_t, nothrow_t)
overloads, because
the core working group decided during the Urbana 2014 meeting, that no change to the core
language was warranted.
[2014-11-23, Daniel suggests concrete wording changes]
[2015-02 Cologne]
Nobody can call those overloads, since the nothrow allocation functions cannot throw. JY: Ship it. GR: Should we do due diligence and make sure we're deleting what we mean to be deleting? [Some checking, everything looks good.]
Accepted.Proposed resolution:
This wording is relative to N4140.
Change 17.6 [support.dynamic], header <new>
synopsis, as indicated:
[…] void operator delete(void* ptr, std::size_t size) noexcept;void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…] void operator delete[](void* ptr, std::size_t size) noexcept;void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…]
Change 17.6.3.2 [new.delete.single], starting before p19, as indicated:
void operator delete(void* ptr, const std::nothrow_t&) noexcept;void operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…]
-20- Replaceable: a C++ program may define a function with signaturevoid operator delete(void* ptr, const std::nothrow_t&) noexcept
that displaces the default version defined by the C++ standard library.If this function (without[…]size
parameter) is defined, the program should also definevoid operator delete(void* ptr, std::size_t size, const std::nothrow_t&) noexcept
. If this function withsize
parameter is defined, the program shall also define the version without thesize
parameter. [Note: The default behavior below may change in the future, which will require replacing both deallocation functions when replacing the allocation function. — end note]-22- Requires: If present, thestd::size_t size
argument must equal thesize
argument passed to the allocation function that returnedptr
.-23- Required behavior: Calls to-24- Default behavior:operator delete(void* ptr, std::size_t size, const std::nothrow_t&)
may be changed to calls tooperator delete(void* ptr, const std::nothrow_t&)
without affecting memory allocation. [Note: A conforming implementation is foroperator delete(void* ptr, std::size_t size, const std::nothrow_t&)
to simply calloperator delete(void* ptr, const std::nothrow_t&)
. — end note]operator delete(void* ptr, std::size_t size, const std::nothrow_t&)
callsoperator delete(ptr, std::nothrow)
, andoperator delete(void* ptr, const std::nothrow_t&)
callsoperator delete(ptr)
.
Change 17.6.3.3 [new.delete.array], starting before p16, as indicated:
void operator delete[](void* ptr, const std::nothrow_t&) noexcept;void operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept;[…]
-17- Replaceable: a C++ program may define a function with signaturevoid operator delete[](void* ptr, const std::nothrow_t&) noexcept
that displaces the default version defined by the C++ standard library.If this function (without[…]size
parameter) is defined, the program should also definevoid operator delete[](void* ptr, std::size_t size, const std::nothrow_t&) noexcept
. If this function withsize
parameter is defined, the program shall also define the version without thesize
parameter. [Note: The default behavior below may change in the future, which will require replacing both deallocation functions when replacing the allocation function. — end note]-19- Requires: If present, thestd::size_t size
argument must equal thesize
argument passed to the allocation function that returnedptr
.-20- Required behavior: Calls to-21- Default behavior:operator delete[](void* ptr, std::size_t size, const std::nothrow_t&)
may be changed to calls tooperator delete[](void* ptr, const std::nothrow_t&)
without affecting memory allocation. [Note: A conforming implementation is foroperator delete[](void* ptr, std::size_t size, const std::nothrow_t&)
to simply calloperator delete[](void* ptr, const std::nothrow_t&)
. — end note]operator delete[](void* ptr, std::size_t size, const std::nothrow_t&)
callsoperator delete[](ptr, std::nothrow)
, andoperator delete[](void* ptr, const std::nothrow_t&)
callsoperator delete[](ptr)
.