exponenta event banner

Правило AUTOSAR C++ 14 A12-8-3

Объект Moved-from не должен быть доступен для чтения

Описание

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

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

Объяснение

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

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

Стандарт 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. См. раздел Преобразование конструктора.