...
It is acceptable to define a deleted allocation or deallocation function without its corresponding free store function. For instance, it is a common practice to define a deleted non-placement allocation or deallocation function as a class member function when the class also defines a placement new
function function. This prevents accidental allocation via calls to new
for that class type , or deallocation via calls to delete
on pointers to an object of that class type. It is acceptable to declare, but not define, a private allocation or deallocation function without its corresponding free store function for similar reasons. However, a definition must not be provided as that still allows access to the free store function within a class member function.
...
In this compliant solution, the corresponding deallocation function is also defined at global scope:.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <Windows.h> #include <new> class HeapAllocator { static HANDLE h; static bool init; public: static void *alloc(std::size_t size) noexcept(false) { if (!init) { h = ::HeapCreate(0, 0, 0); // Private, expandable heap. init = true; } if (h) { return ::HeapAlloc(h, 0, size); } throw std::bad_alloc(); } static void dealloc(void *ptr) noexcept { if (h) { (void)::HeapFree(h, 0, ptr); } } }; HANDLE HeapAllocator::h = nullptr; bool HeapAllocator::init = false; void *operator new(std::size_t size) noexcept(false) { return HeapAllocator::alloc(size); } void operator delete(void *ptr) noexcept { return HeapAllocator::dealloc(ptr); } |
...
In this compliant solution, the corresponding operator delete()
is overloaded at the same class scope:.
Code Block | ||||
---|---|---|---|---|
| ||||
#include <new> extern "C++" void update_bookkeeping(void *allocated_ptr, std::size_t size, bool alloc); struct S { void *operator new(std::size_t size) noexcept(false) { void *ptr = ::operator new(size); update_bookkeeping(ptr, size, true); return ptr; } void operator delete(void *ptr, std::size_t size) noexcept { ::operator delete(ptr); update_bookkeeping(ptr, size, false); } }; |
...
DCL54-CPP-EX1: A placement deallocation function may be elided for a corresponding placement allocation function, but only if the object placement allocation and object construction are guaranteed to be noexcept(true)
. Because placement deallocation functions are automatically invoked when some part of the object initialization throws terminates by throwing an exception, it is safe to elide the placement deallocation function when exceptions cannot be thrown. For instance, some vendors implement compiler flags disabling exception support (such as -fno-cxx-exceptions in Clang and /EHs-c- in Microsoft Visual Studio), which has implementation-defined behavior when an exception is thrown but generally results in program termination similar to calling abort()
.
...
Mismatched usage of new
and delete
could lead to a denial-of-service attack.
Rule | Severity | Likelihood | Remediation Cost | Priority | Level |
---|---|---|---|---|---|
DCL54-CPP | Low | Probable | Low | P6 | L2 |
Automated Detection
Tool | Version | Checker | Description | ||||||
---|---|---|---|---|---|---|---|---|---|
Astrée |
| new-delete-pairwise | Partially checked | ||||||
Axivion Bauhaus Suite |
| CertC++-DCL54 | |||||||
Clang |
| misc-new-delete-overloads | Checked with clang-tidy . | ||||||
Helix QAC |
| C++2160 | |||||||
Klocwork |
| CERT.DCL.SAME_SCOPE_ALLOC_DEALLOC | |||||||
Parasoft C/C++test |
2161
| CERT_CPP-DCL54-a | Always provide new and delete together | |||||||
Polyspace Bug Finder |
| CERT C++: DCL54-CPP | Checks for mismatch between overloaded operator new and operator delete (rule fully covered) | ||||||
RuleChecker |
| new-delete-pairwise | Partially checked |
SonarQube C/C++ Plugin |
| S1265 |
Related Vulnerabilities
Search for vulnerabilities resulting from the violation of this rule on the CERT website.
Related Guidelines
Bibliography
[ISO/IEC 14882-2014] | Subclause 3.7.4, "Dynamic Storage Duration" |
|
...