ПроблемаЭта проблема происходит, когда вы используете уже принадлежавший указатель в качестве аргумента:
Конструктор интеллектуального указателя. Например, в этом фрагменте кода, 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
. Базовое значение указателя не удалено, пока все интеллектуальные указатели не уничтожаются.