CERT C++: MEM56-CPP

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

Описание

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

Не храните уже принадлежавшее значение указателя в несвязанном умном pointer.[1]

Реализация Polyspace

Это средство проверки проверяет на Use of already-owned pointers

Примеры

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

Проблема

Эта проблема происходит, когда вы используете уже принадлежавший указатель в качестве аргумента:

  • Конструктор интеллектуального указателя. Например, в этом фрагменте кода, 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-> функция членства.

Риск

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

Фиксация

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

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

Пример — использование уже принадлежавшего указателя
#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

}

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

Коррекция — использует std::make_shared и скопируйте конструкцию, чтобы создать связанные интеллектуальные указатели
#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 func2(){

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

}

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

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

Группа: правило 06. Управление памятью (MEM)
Введенный в R2021a

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ-МЕЛЛОН И/ИЛИ ЕГО ИНСТИТУТА ПРОГРАММНОЙ ИНЖЕНЕРИИ СОДЕРЖАЛ, ЗДЕСЬ ПРЕДОСТАВЛЯЕТСЯ НА БАЗИСЕ "ASIS". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.