Main Content

AUTOSAR C++14 Rule A18-1-4

A pointer pointing to an element of an array of objects shall not be passed to a smart pointer of single object type

Since R2022a

Description

Rule Definition

A pointer pointing to an element of an array of objects shall not be passed to a smart pointer of single object type.

Rationale

You must deallocate pointers to array elements by using delete[] instead of delete.

A pointer to an array element being passed to a smart pointer of single object type results in undefined behavior. Consider this code:

typedef A cArr[10];
std::unique_ptr<A> smartPtr1{new cArr};  //Noncompliant 

cArr and its elements require delete[]. However, smartPtr1 attempts to deallocate by using delete, resulting in undefined behavior.

Consider the following alternatives:

  • Avoid using smart pointers to a pointer to an item in an array of objects. Instead use:

    • std::array

    • std::vector

    • std::shared_ptr<std::vector<T>>

  • std::unique_ptr<T[]> and the corresponding overloads for std::make_unique.

    As of C++17, you can use std::shared_ptr<T[]>. The corresponding overloads for std::make_shared are not introduced until C++20.

Creating a custom deleter capable of handling an array of objects for the smart pointer of a single object type is considered noncompliant with this rule. This alternative can be error-prone, might no longer be supported in C++17, and is superseded by alternatives such as std::unique_ptr<T[]>.

Polyspace Implementation

Polyspace® raises this defect when you pass a pointer pointing to an element in an array of objects to a smart pointer of a single object. Polyspace also raises this defect if you pass a C-style array to a smart pointer of a single object.

Polyspace raises this defect when these conditions are met:

  • You create a smart pointer by using std::unique_ptr<T> or std::shared_ptr<T>.

  • You create an array of objects by using a C-style array or you create an array by using std::make_unique or std::make_shared.

  • You use a function member of the smart pointer such as release() or get() to obtain the pointer to pass to the smart pointer.

You can pass the pointer to a smart pointer in several ways, including using a copy constructor, move constructor, or the reset() member function of the smart pointer.

When using a copy or move constructor, Polyspace flags the checker on the declared object name. In the case of a reset() member function, Polyspace flags the checker on the reset() member function.

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 <cstdint>
#include <vector>
#include <memory>

size_t x = 10;
class A
{
};

void example()
{
    std::unique_ptr<A[]> uPoint = std::make_unique<A[]>(x);
    std::shared_ptr<A> smartPtr1{ uPoint.get() };             //Noncompliant

    std::unique_ptr<A> smartPtr2;
    smartPtr2.reset(uPoint.release());                        //Noncompliant

    std::shared_ptr<std::vector<A>> smartPtr3;                //Compliant
}

There are two noncompliant smart pointers in the preceding example, smartPtr1 and smartPtr2.

Both examples are noncompliant as, in each, a pointer to an array element is passed to a smart pointer that manages a single object, resulting in undefined behavior.

#include <cstdint>
#include <iostream>
#include <memory>

class A {
};

void Ex2()
{
    typedef A cArr[10];
    std::unique_ptr<A> smartPtr1{ new cArr };      //Noncompliant
    std::shared_ptr<A> smartPtr2{ new cArr };      //Noncompliant

    cArr a;
    std::unique_ptr<A> smartPtr3{ a };             //Noncompliant 
    std::unique_ptr<A[]> smartPtr4{ a };           //Compliant
}

Because the C-style array is passed to the constructor of a smart pointer of a single object, Polyspace flags it as noncompliant. It does not matter if you create the smart pointer by using std::unique_ptr or std::shared_ptr. Both options are noncompliant.

Use of a specialized standard library template such as std::unique_ptr<T[]> as used in the example is compliant as long as you are using a compatible code version.

Check Information

Group: Language support library
Category: Required, Automated

Version History

Introduced in R2022a