AUTOSAR C++14 Rule A20-8-1

Уже принадлежавшее значение указателя не должно храниться в несвязанном интеллектуальном указателе

Описание

Управляйте определением

Уже принадлежавшее значение указателя не должно храниться в несвязанном интеллектуальном указателе.

Объяснение

Вы используете интеллектуальные указатели, чтобы гарантировать, что память, на которую указывает указатель, автоматически освобождена, когда указатель уничтожается, например, если указатель выходит из осциллографа. Когда несвязанные интеллектуальные указатели управляют тем же значением указателя, один из интеллектуальных указателей может попытаться освободить память, которая была уже освобождена другим интеллектуальным указателем. Это приводит к двойной свободной уязвимости, которая повреждает структуру данных управления памятью вашей программы.

Интеллектуальный указатель владеет значением указателя, которое используется, чтобы инициализировать интеллектуальный указатель. Если значение указателя уже принадлежит интеллектуальному указателю, такому как std::shared_ptr, и затем вы используете тот интеллектуальный указатель, чтобы инициализировать другой интеллектуальный указатель, например, с операцией копии, эти два интеллектуальных указателя связаны. Базовое значение указателя управляемо обоими интеллектуальными указателями, и память указала, не освобожден, пока все интеллектуальные указатели не уничтожаются.

Реализация Polyspace

Polyspace® отмечает использование уже принадлежавшего указателя в качестве аргумента:

  • Конструктор интеллектуального указателя. Например, в этом фрагменте кода, raw_ptr уже принадлежит s_ptr1 и используется, чтобы инициализировать s_ptr2:

    char *raw_ptr = new char;
    std::shared_ptr<char> s_ptr1(raw_ptr);
    std::shared_ptr<char> s_ptr2(raw_ptr); //raw_ptr is already owned by s_ptr1

  • Интеллектуальный указатель сбросил операцию. Например, в этом фрагменте кода, сбросе s_ptr2 замены raw_ptr2 с уже принадлежавшим raw_ptr1:

    char *raw_ptr1 = new char;
    char *raw_ptr2 = new char;
    
    std::shared_ptr<char> s_ptr1(raw_ptr1);
    std::shared_ptr<char> s_ptr2(raw_ptr2);
    
    s_ptr2.reset(raw_ptr1); // s_ptr2 releases raw_ptr2 and owns already owned raw_ptr1

Polyspace проверяет, что только интеллектуальный указатель вводит std::shared_ptr и std::unique_ptr и полагает, что пользовательские средства выделения и средства удаления имеют стандартное поведение выделения и освобождения.

Указатель уже принадлежит интеллектуальному указателю, если типом указателя не является std::nullptr_t и также:

  • Указатель использовался, чтобы инициализировать интеллектуальный указатель.

  • Указатель использовался в качестве аргумента к интеллектуальному указателю reset() функция членства.

  • Указатель является возвращаемым значением интеллектуального указателя get() функция членства.

  • Указатель является возвращаемым значением интеллектуального указателя operator-> функция членства.

Поиск и устранение проблем

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

развернуть все

#include <memory>
#include <string>

struct Profile
{
    virtual ~Profile()=default;
};

struct Player : public Profile
{
    std::string name;
    std::int8_t rank;

    Player();
    Player(const std::string& name_, const std::int8_t& rank_) :
        name{ name_ }, rank{ rank_ } {}
};

void func(){

    Player * player = new Player("Richard Roll",1);
    std::shared_ptr<Player> player1(player);
    std::shared_ptr<Player> top_rank(player); //Non-compliant

}

void func2(){

    std::shared_ptr<Player> player1_shared =
        std::make_shared<Player>("Richard Roll",1);
    std::shared_ptr<Player> top_rank_shared(player1_shared); //Compliant

}

В этом примере, использовании значения указателя player создать интеллектуальный указатель top_rank в функциональном func несовместимо. player уже принадлежит интеллектуальному указателю player1. Когда player1 уничтожается, это может попытаться удалить значение указателя player который был уже удален top_rank.

Если вы намереваетесь иметь несколько, интеллектуальный указатель управляет тем же значением указателя, использует std::make_shared объявить player1_shared, и затем используйте конструкцию копии, чтобы создать связанный интеллектуальный указатель top_rank_shared, как в func2. Базовое значение указателя не удалено, пока все интеллектуальные указатели не уничтожаются.

Если вы не намереваетесь совместно использовать значение указателя между интеллектуальными указателями, используйте std::make_unique создать интеллектуальный указатель типа std::unique_ptr. std::unique_ptr может только быть перемещен, который оставляет владение базового значения управляемого указателя.

Проверяйте информацию

Группа: Общая сервисная библиотека
Категория: необходимый, автоматизированный
Введенный в R2021a