AUTOSAR C++14 Rule A12-8-3

Перемещенный из объекта не должен быть получен доступ для чтения

Описание

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

Доступ к объекту, перемещенному из объекта, не допускается.

Объяснение

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

Операции, которые не делают никаких допущений о состоянии объекта, не нарушают это правило.

Стандарт C++ задает, что эти операции перемещения оставляют исходный объект в четко заданном состоянии после перемещения:

  • Перемещение конструкции, назначение перемещения, преобразование[1] перемещение конструкции и преобразование назначения перемещения std::unique_ptr напечатать

  • Перемещение конструкции, назначение перемещения, преобразование конструкции перемещения, преобразование назначения перемещения std::shared_ptr напечатать

  • Перемещение конструкции и перемещение назначения из std::unique_ptr от std::shared_ptr напечатать

  • Перемещение конструкции, назначение перемещения, преобразование конструкции перемещения и преобразование назначения перемещения std::weak_ptr напечатать

  • std::move() от std::basic_ios напечатать

  • Перемещайте конструктор и перемещайте назначение std::basic_filebuf напечатать

  • Перемещайте конструктор и перемещайте назначение std::thread напечатать

  • Перемещайте конструктор и перемещайте назначение std: unique_lock напечатать

  • Перемещайте конструктор и перемещайте назначение std::shared_lock напечатать

  • Перемещайте конструктор и перемещайте назначение std::promise напечатать

  • Перемещайте конструктор и перемещайте назначение std::future напечатать

  • Перемещение конструкции, назначение перемещения, преобразование конструкции перемещения и преобразование назначения перемещения std::shared_future напечатать

  • Перемещайте конструктор и перемещайте назначение std::packaged_task напечатать

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

Реализация Polyspace

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.

Поиск и устранение проблем

Если вы ожидаете нарушения правил, но не видите его, обратитесь к разделу «Стандартные нарушения кодирования не отображаются».

Примеры

расширить все

В этом примере показано, как Polyspace помечает чтение исходного объекта после явной операции перемещения.

#include<string>
#include<iostream>
void F1()
{
	std::string s1{"string"};
	std::string s2{std::move(s1)}; 
	// ...
	std::cout
	<<  // Noncompliant
	s1
	<< "\n";
}

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 F3()
{
	std::string s;
	for (unsigned i = 0; i < 10; ++i) {
		s.append(1, static_cast<char>('0' + i));  //Noncompliant 
		g(std::move(s));
	}
}
void F4()
{
	for (unsigned i = 0; i < 10; ++i) {
		std::string s(1, static_cast<char>('0' + i)); // Compliant
		g(std::move(s));  
	}
}

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

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

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

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

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

Группа: Специальные функции представителей
Категория: Требуемая, Частично автоматизированная
Введенный в R2021a

[1] Преобразовывающий конструктор является конструктором, который не объявлен со спецификатором explicit. См. Преобразование конструктора.