exponenta event banner

CERT C++: OOP54-CPP

Изящная обработка назначения самокопии

Описание

Определение правила

Изящно обработайте назначение самокопирования. [1 ]

Внедрение Polyspace

Эта проверка проверяет наличие самоназначения, не протестированного в операторе.

Примеры

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

Проблема

Самоназначение, не проверенное в операторе, возникает, когда не проверяется, является ли аргумент для оператора копирования назначения объекта самим объектом.

Риск

Самостоятельное назначение вызывает ненужное копирование. Хотя маловероятно, что объект назначается самому себе, из-за наложения псевдонимов вы или пользователи вашего класса не всегда могут обнаружить самостоятельное назначение.

Самостоятельное назначение может привести к тонким ошибкам, если элемент данных является указателем, а память выделяется указателю динамически. В операторе присвоения копирования обычно выполняются следующие шаги:

  1. Отмена выделения памяти, первоначально связанной с указателем.

    delete ptr;
    
  2. Выделение новой памяти указателю. Инициализируйте новую ячейку памяти с содержимым, полученным из аргумента оператора.

     ptr = new ptrType(*(opArgument.ptr));
    

Если аргумент оператору, opArgument, является сам объект, после вашего первого шага, элемент данных указателя в аргументе оператора, opArgument.ptr, не связан с расположением памяти. *opArgument.ptr содержит непредсказуемые значения. Поэтому на втором шаге выполняется инициализация новой ячейки памяти с непредсказуемыми значениями.

Зафиксировать

Проверьте самоназначение в операторе присвоения копии класса. Только после тестирования выполните назначения в операторе присвоения копирования.

Пример - Отсутствие теста для самостоятельного назначения
class MyClass1 { };
class MyClass2 {
public:
    MyClass2()                : p_(new MyClass1())      { }
    MyClass2(const MyClass2& f)   : p_(new MyClass1(*f.p_)) { }
    ~MyClass2()                {
        delete p_;
    }
    MyClass2& operator= (const MyClass2& f)
    {
        delete p_;
        p_ = new MyClass1(*f.p_);
        return *this;
    }
private:
    MyClass1* p_;
};

В этом примере оператор присвоения копирования в MyClass2 не проверяет самоназначение. Если параметр f является текущим объектом, после оператора delete p_, память, выделенная указателю f.p_ также освобождается. Поэтому заявление p_ = new MyClass1(*f.p_) инициализирует расположение памяти, p_ указывает на с непредсказуемыми значениями.

Коррекция - тест на самостоятельное присвоение

Одной из возможных корректировок является проверка самостоятельного присвоения в операторе присвоения копии.

class MyClass1 { };
class MyClass2 {
public:
    MyClass2()                : p_(new MyClass1())      { }
    MyClass2(const MyClass2& f)   : p_(new MyClass1(*f.p_)) { }
    ~MyClass2()                {
        delete p_;
    }
    MyClass2& operator= (const MyClass2& f)
    {
        if(&f != this) {
           delete p_;
           p_ = new MyClass1(*f.p_);
        }
        return *this;
    }
private:
    MyClass1* p_;
};

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

Группа: 09. Объектно-ориентированное программирование (ООП)
Представлен в R2019a

[1] Данное программное обеспечение было создано компанией MathWorks и включает в себя следующие компоненты: «Веб-сайт SEI CERT-C», © 2017 Университет Карнеги-Меллон, веб-сайт SEI CERT-C + + © 2017 Университет Карнеги-Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги-Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги-Меллон, со специальным разрешением от его Института программного обеспечения.

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

Данное программное обеспечение и связанная с ним документация не были рассмотрены и не одобрены Университетом Карнеги-Меллона или его Институтом разработки программного обеспечения.