exponenta event banner

CERT C++: EXP63-CPP

Не полагаться на значение объекта, перемещенного из

Описание

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

Не полагайтесь на значение объекта, перемещенного из [1 ].

Внедрение Polyspace

Эта проверка проверяет чтение значения объекта, перемещенного из.

Примеры

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

Проблема

Эта проблема возникает, когда значение исходного объекта считывается после перемещения его содержимого в целевой объект путем вызова std::move функция явно. Polyspace ® не помечает доступ к значению перемещенного объекта, если:

  • Исходный объект операции явного перемещения имеет следующие типы:

    • std::unique_ptr

    • std::shared_ptr

    • std::weak_ptr

    • std::basic_ios

    • std::basic_filebuf

    • std::thread

    • std::unique_lock

    • std::shared_lock

    • std::promise

    • std::future

    • std::shared_future

    • std::packaged_task

    Эти объекты не остаются в неопределенном состоянии после явного перемещения их состояния.

  • Операция перемещения выполняется неявно. Например, функция std::remove может получить доступ к состоянию исходного объекта после неявной операции перемещения. Polyspace не помечает его. Оптимальная практика заключается в том, чтобы избегать таких операций и использовать более безопасные альтернативы, которые предотвращают случайный доступ, такие как std::erase.

  • Исходный объект имеет встроенный базовый тип, например: int, enum, float, double, указатель, std::intptr_t, std::nullptr_t.

Риск

Поскольку состояние исходного объекта обычно не определено после операции перемещения, небезопасно выполнять операции, зависящие от состояния исходного объекта после операции перемещения. Обращение к состоянию исходного объекта после операции перемещения может привести к нарушению целостности данных, непредвиденному значению или недопустимой отмене ссылки на указатель.

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

Избегайте операций, которые могут считывать исходный объект после перемещения его содержимого.

Пример - Чтение значения исходного объекта после вызова std::move
#include<string>
#include<iostream>
void F1()
{
	std::string s1{"string"};
	std::string s2{std::move(s1)}; 
	// ...
	std::cout
	<<  // Noncompliant
	s1
	<< "\n";
	// value after move operation
}
void g(std::string v)
{
	std::cout << v << std::endl; 
}

void F3()
{
	std::string s;
	for (unsigned i = 0; i < 10; ++i) {
		s.append(1, static_cast<char>('0' + i));  //Noncompliant 
		g(std::move(s));
	}
}

  • В функции F1, строка s1 явно перемещен в s2 путем вызова std::move. После операции перемещения функция пытается прочитать s1. Polyspace помечает эту попытку чтения исходного объекта после явного перемещения.

  • В функции F3, строка s явно перемещается, а затем считывается std::string::append функция. Polyspace помечает эту попытку чтения исходного объекта после явного перемещения.

Исправление - считывание значений исходных объектов в указанном состоянии
#include<string>
#include<iostream>
void F2()
{
	std::unique_ptr<std::int32_t> ptr1 = std::make_unique<std::int32_t>(0);
	std::unique_ptr<std::int32_t> ptr2{std::move(ptr1)};
	std::cout << ptr1.get() << std::endl; // Compliant by exception
}
void g(std::string v)
{
	std::cout << v << std::endl; 
}
void F4()
{
	for (unsigned i = 0; i < 10; ++i) {
		std::string s(1, static_cast<char>('0' + i)); // Compliant
		g(std::move(s));  
	}
}

  • В функции F2, уникальный указатель ptr1 явно перемещен в ptr2. Потому что состояние std::unique_ptr остается в указанном состоянии после перемещения, считывая уникальный указатель источника после того, как явное перемещение совместимо.

  • В функции F4, строка s явно перемещен. В каждой итерации цикла s инициируется для определенного содержимого до запуска операции перемещения. В результате состояние s задается до обращения к объекту. Этот метод доступа к исходному объекту после операции перемещения соответствует этому правилу.

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

Группа: Правило 02. Выражения (EXP)
Представлен в R2021a

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

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

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