...
Code Block | ||||
---|---|---|---|---|
| ||||
#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 | ||||
---|---|---|---|---|
| ||||
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 | ||||
---|---|---|---|---|
| ||||
#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 | ||||
---|---|---|---|---|
| ||||
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" |
[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