Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Added content from the soon-to-be-voided MEM36-CPP

...

Code Block
bgColor#ccccff
langcpp
#include <cstring>
 
void f(const int *array, std::size_t size) noexcept(false) {
  int *copy = new int[size];
  // If the allocation fails, it will throw an exception which the caller
  // will have to handle.
  std::memcpy(copy, array, size * sizeof *copy);
  // ...
  delete [] copy;
}

Noncompliant Code Example

In this noncompliant code example, two memory allocations are performed within the same expression. Because the memory allocations are passed as arguments to a function call, an exception thrown as a result of one of the calls to new could result in a memory leak.

Code Block
bgColor#FFcccc
langcpp
struct A { /* ... */ };
struct B { /* ... */ }; 
 
void g(A *, B *);
void f() {
  g(new A, new B);
}

Consider the situation where A is allocated and constructed first, and then B is allocated and throws an exception. Wrapping the call to g() in a try/catch block is insufficient because it would be impossible to free the memory allocated for A.

Compliant Solution (std::unique_ptr)

In this compliant solution, a std::unique_ptr is used to manage the resources for the A and B objects. In the situation described by the noncompliant code example, B throwing an exception would still result in the destruction and deallocation of the A object when then std::unique_ptr<A> was destroyed.

Code Block
bgColor#ccccff
langcpp
#include <memory>
 
struct A { /* ... */ };
struct B { /* ... */ }; 
 
void g(std::unique_ptr<A> a, std::unique_ptr<B> b);
void f() {
  g(std::make_unique<A>(), std::make_unique<B>());
}

Compliant Solution (References)

When possible, the more resilient compliant solution is to remove the memory allocation entirely, and pass the objects by reference instead:

Code Block
bgColor#ccccff
langcpp
struct A { /* ... */ };
struct B { /* ... */ }; 
 
void g(A &a, B &b);
void f() {
  A a;
  B b;
  g(a, b);
}

Risk Assessment

Failing to detect allocation failures can lead to abnormal program termination and denial-of-service attacks.

...

[ISO/IEC 14882-2014]

18.6.1.1, "Single-object Forms"
18.6.1.2, "Array Forms"
20.7.9.1, "Allocator Members"

[ISO/IEC 9899:2011]Section 7.20.3, "Memory management functions"
[Meyers 95]Item 7. Be prepared for out-of-memory conditions.
[Seacord 052013b]Chapter 4, "Dynamic Memory Management"

 

MEM31-CPP. Free dynamically allocated memory exactly once      08. Memory Management (MEM)      MEM33-CPP. Ensure that aborted constructors do not leak