Rule A18-5-2 (required, implementation, partially automated)
Non-placement new or delete expressions shall not be used.
Rationale
If a resource returned by a non-placement new expression is assigned to a raw pointer, then a developer’s mistake, an exception or a return may lead to memory leak.
It is highly recommended to follow RAII design pattern or use manager objects that manage the lifetime of variables with dynamic storage duration, e.g.: std::unique_ptr along with std::make_unique
std::shared_ptr along with std::make_shared std::string std::vector Note: Functions that do not extend lifetime shall not take parameters as smart pointers, see A8-4-11.
Exception
If the result of explicit resource allocation using a new expression is immediately passed to a manager object or an RAII class which does not provide a safe alternative for memory allocation, then it is not a violation of this rule. This rule does not apply to dynamic memory allocation/deallocation performed in user-defined RAII classes and managers. Placement new expression is allowed, see A18-5-10.
Example
// $Id: A18-5-2.cpp 316977 2018-04-20 12:37:31Z christof.meerwald $
#include <cstdint>
#include <memory>
#include <vector>
std::int32_t Fn1()
{
std::int32_t errorCode{0};
std::int32_t* ptr =
new std::int32_t{0}; // Non-compliant - new expression
// ...
if (errorCode != 0)
{
throw std::runtime_error{"Error"}; // Memory leak could occur here
}
// ...
if (errorCode != 0)
{
return 1; // Memory leak could occur here
}
// ...
delete ptr; // Non-compilant - delete expression
return errorCode;
}
std::int32_t Fn2()
{
std::int32_t errorCode{0};
std::unique_ptr<std::int32_t> ptr1 = std::make_unique<std::int32_t>(
0); // Compliant - alternative for ’new std::int32_t(0)’
std::unique_ptr<std::int32_t> ptr2(new std::int32_t{
0}); // Non-compliant - unique_ptr provides make_unique
// function which
shall be used instead of explicit
// new expression
std::shared_ptr<std::int32_t> ptr3 =
std::make_shared<std::int32_t>(0); // Compliant
std::vector<std::int32_t> array; // Compliant
// alternative for dynamic array
if (errorCode != 0)
{
throw std::runtime_error{"Error"}; // No memory leaks
}
// ...
if (errorCode != 0)
{
return 1; // No memory leaks
}
// ...
return errorCode; // No memory leaks
}
template <typename T>
class ObjectManager
{
public:
explicit ObjectManager(T* obj) : object{obj} {}
~ObjectManager() { delete object; } // Compliant by exception
// Implementation
private:
T* object;
};
std::int32_t Fn3()
{
std::int32_t errorCode{0};
ObjectManager<std::int32_t> manager{
new std::int32_t{0}}; // Compliant by exception
if (errorCode != 0)
{
throw std::runtime_error{"Error"}; // No memory leak
}
// ...
if (errorCode != 0)
{
return 1; // No memory leak
}
// ...
return errorCode; // No memory leak
}
See also
C++ Core Guidelines [11]: R.11: Avoid calling new and delete explicitly. C++ Core Guidelines [11]: R.12: Immediately give the result of an explicit resource allocation to a manager object. C++ Core Guidelines [11]: ES.60: Avoid new and delete outside resource management functions.