Main Content

AUTOSAR C++14 Rule A20-8-6

std::make_shared shall be used to construct objects owned by std::shared_ptr

Since R2020b

Description

Rule Definition

std::make_shared shall be used to construct objects owned by std::shared_ptr.

Rationale

Create a std::shared_ptr object directly by using the std::make_shared function:

auto numberPtr = std::make_shared<numberClass>(aNumber);
Avoid creating std::shared_ptr objects by converting raw pointers to dynamic memory:
class numberClass {
   public:
     numberClass(int n): number(n){}
   private: 
     int number;
}
int aNumber=1; 
std::shared_ptr<numberClass> numberPtr (new numberClass(aNumber)); 

Using std::make_shared is preferred because:

  • The creation of the std::shared_ptr object is performed in a single dynamic memory allocation and improves run-time performance. Otherwise, creating a raw pointer by using the new operator requires one dynamic memory allocation and converting the raw pointer to an std::shared_ptr object requires a second allocation. The second allocation creates a control block that keeps track of the reference count of the shared resource and makes the std::shared_ptr object aware of all pointers to the shared resource.

  • The creation of the std::shared_ptr object using std::make_shared is exception-safe. Otherwise, an exception can occur between the dynamic memory allocation with the new operator and the subsequent conversion, leading to a memory leak. An exception causes a memory leak only in certain contexts, for instance, when the std::shared_ptr object is created in an argument of a multi-parameter function and another function argument evaluation throws an exception.

  • You can use a more concise syntax. You do not have to repeat the data type of the object that is dynamically allocated.

Polyspace Implementation

The checker flags the creation of an std::shared_ptr object (or boost::shared_ptr object) from the raw pointer returned by the new operator.

Troubleshooting

If you expect a rule violation but Polyspace® does not report it, see Diagnose Why Coding Standard Violations Do Not Appear as Expected.

Examples

expand all

#include<memory>
#include <cstdint>
#include <string>

class Record {
public:
	Record() = default;
	Record(std::string aName, std::string someInfo): name(aName), info(someInfo){       
	}
private:
	std::string name;
	std::string info;
};

void addRecordToDataBase(std::shared_ptr<Record> aRecord, bool dataBaseIsFull);
bool checkDataBase(void); //Checks if database can accept more entries

void createRecord() {
	std::shared_ptr<Record> recordPtr1 (new Record("John", "Mechanic, New York")); //Noncompliant
	auto recordPtr2 = std::make_shared<Record>("Tom", "Plumber, Boston"); //Compliant
	//...
	addRecordToDataBase(std::shared_ptr<Record>(new Record("John", "Mechanic, New York")), checkDataBase()); //Noncompliant
	addRecordToDataBase(std::make_shared<Record>("Tom", "Plumber, Boston"), checkDataBase()); //Compliant
	//...
}

std::shared_ptr<Record> getSP(void) {
	std::shared_ptr<Record> result{std::make_shared<Record>()};//Compliant 
	return result;                                                      
}

In this example, the rule is violated whenever the new operator returns a raw pointer and a subsequent conversion creates an std::shared_ptr object from the raw pointer.

In the first call to addRecordToDatabase, the following sequence of events can occur (prior to C++17):

  • First argument evaluation. The new operator dynamically allocates memory for a Record object.

  • Second argument evaluation. The function checkDataBase is called.

  • Continuation of first argument evaluation. The raw pointer obtained from new is converted to an std::shared_ptr object.

If the second step throws an exception, the raw pointer is not assigned to the resource management object and results in a memory leak. Polyspace flags the first call to addRecordToDatabase.

In the function getSP(), the shared pointer result is copy constructed from a temporary shared_ptr object. An implicit copying of the shared pointer also takes place during the return statement. Polyspace does not flag these operations.

Check Information

Group: General utilities library
Category: Required, Automated

Version History

Introduced in R2020b

expand all