CERT C++: OOP54-CPP

Корректно обработайте присвоение самокопии

Описание

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

Корректно обработайте присвоение самокопии. [1]

Примеры

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

Описание

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

Риск

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

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

  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. Объектно-ориентированное программирование (OOP)

Введенный в R2019a


[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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ВЫРАЗИЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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