CERT.DCL.SAME_SCOPE_ALLOC_DEALLOC

Overload allocation and deallocation functions as a pair in the same scope.

Overload allocation and deallocation functions as a pair in the same scope.

Vulernability and risk

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 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 data for the custom allocator.

Mitigation and prevention

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

Example

Copy
  #include <Windows.h>
  #include <new>
  
  extern "C++" void update_bookkeeping(void *allocated_ptr, std::size_t size, bool alloc);
  
  void *operator new(std::size_t size) noexcept(false) {     // uncompliant code, it only overloads 'new' in std namespace, not 'delete'.
    static HANDLE h = ::HeapCreate(0, 0, 0); // Private, expandable heap.
    if (h) {
      return ::HeapAlloc(h, 0, size);
   }
   throw std::bad_alloc();
 }
 
 struct S_positive {
   void *operator new(std::size_t size) noexcept(false) {
     void *ptr = ::operator new(size);
     update_bookkeeping(ptr, size, true);                        // uncompliant code
     return ptr;
   }
 };
 
 struct S_negative {                                                        // compliant code
   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);
   }
 };

There is no corresponded deallocation method overloaded in the same scope for the allocation methods in line 6, and 15. The compliant situation is the allocation method overloaded in line 38 because there is the corresponded deallocation method overloaded in line 29.