CERT C++: EXP63-CPP

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

Описание

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

Не используйте значение перемещенного - от object.[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 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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