Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

If an allocation function is overloaded in a given scope, the corresponding deallocation function should must also be overloaded in the same scope (and vice versa).

Failure to overload the corresponding dynamic storage function is likely to violate rules such as MEM51-CPP. Properly deallocate dynamically allocated resources. For instance, if an overloaded allocation function uses a private heap to perform its allocations, passing a pointer returned by it to the default deallocation function will likely cause undefined behavior. Even in situations in which the allocation function ultimately calls through to uses the default allocator to obtain a pointer to memory, failing to overload a corresponding deallocation function may leave the program in an unexpected state by not updating internal allocator statedata for the custom allocator.

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.

Noncompliant Code Example

...

Code Block
bgColor#FFcccc
langcpp
#include <Windows.h>
#include <new>
 
void *operator new(std::size_t size) noexcept(false) {
  static HANDLE Hh = ::HeapCreate(0, 0, 0); // Private, expandable heap.
  if (Hh) {
    return ::HeapAlloc(Hh, 0, size);
  }
  throw std::bad_alloc();
}
 
// No corresponding global delete operator defined.

Compliant Solution

In this compliant solution, the corresponding deallocation function is also defined at global scope:.

Code Block
bgColor#ccccff
langcpp
#include <Windows.h>
#include <new>

class HeapAllocator {
  static HANDLE Hh;
  static bool Initinit;
 
public:
  static void *alloc(std::size_t size) noexcept(false) {
    if (!Initinit) {
      Hh = ::HeapCreate(0, 0, 0); // Private, expandable heap.
      Initinit = true;
    }
 
    if (Hh) {
      return ::HeapAlloc(Hh, 0, size);
    }
    throw std::bad_alloc();
  }
 
  static void dealloc(void *ptr) noexcept {
    if (Hh) {
      (void)::HeapFree(Hh, 0, ptr);
    }
  }
};
 
HANDLE HeapAllocator::Hh = nullptr;
bool HeapAllocator::Initinit = false;

void *operator new(std::size_t size) noexcept(false) {
  return HeapAllocator::alloc(size);
}
 
void operator delete(void *ptr) noexcept {
  return HeapAllocator::dealloc(ptr);
}
Page properties
hiddentrue

This code has a race condition. We should (1) fix the race condition, and (2) point to a rule about preventing race conditions (that we don't currently have!).

Noncompliant Code Example

...

In this compliant solution, the corresponding operator delete() is overloaded at the same class scope:.

Code Block
bgColor#ccccff
langcpp
#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 called only when some part of automatically invoked when the object initialization 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

PRQA QA-C++ Include PagePRQA QA-C++_VPRQA QA-C++_V2160, 2161 

Astrée

Include Page
Astrée_V
Astrée_V

new-delete-pairwise
Partially checked
Axivion Bauhaus Suite

Include Page
Axivion Bauhaus Suite_V
Axivion Bauhaus Suite_V

CertC++-DCL54
Clang
Include Page
Clang_38_V
Clang_38_V
misc-new-delete-overloadsChecked with clang-tidy.
Helix QAC

Include Page
Helix QAC_V
Helix QAC_V

C++2160
Klocwork
Include Page
Klocwork_V
Klocwork_V
CERT.DCL.SAME_SCOPE_ALLOC_DEALLOC 
Parasoft C/C++test
Include Page
Parasoft_V
Parasoft_V
CERT_CPP-DCL54-a

Always provide new and delete together

Polyspace Bug Finder

Include Page
Polyspace Bug Finder_V
Polyspace Bug Finder_V

CERT C++: DCL54-CPPChecks for mismatch between overloaded operator new and operator delete (rule fully covered)
RuleChecker
Include Page
RuleChecker_V
RuleChecker_V
new-delete-pairwise
Partially checked
SonarQube C/C++ Plugin
Include Page
SonarQube C/C++ Plugin_V
SonarQube C/C++ Plugin_V
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"
Subclause 5.3.4, "New"
Subclause 5.3.5, "Delete"

 

 


...

Image Modified Image Modified Image Modified