...
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. 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);
}
}; |
...
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" |
|
...