exponenta event banner

AUTOSAR C++14 Rule A15-5-1

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

Описание

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

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

Объяснение

Это говорит, что определенные функции не должны выходить за исключением.

  • Деструкторы и функции деаллокации: Когда возникает исключение, компилятор вызывает деструкторы и функции деаллокации, чтобы безопасно удалить объекты в стеке. Если в это время деструктор или функция деаллокации выходят за исключением, компилятор прекращает выполнение программы ненормально. В зависимости от программного обеспечения или оборудования, которое вы используете, ненормальное прекращение работы программы может привести к утечкам ресурсов и уязвимостям безопасности. Чтобы предотвратить эти проблемы, избегайте деструкторов и функций деаллокатора, которые могут выйти за исключением. Деструкторы и деаллокаторы по умолчанию noexcept функций. Когда вы предоставляете пользовательский деструктор или функцию удаления, задайте их следующим noexcept и обрабатывать все исключения в функции, чтобы они не выходили за исключением. Для иерархии полиморфных классов это правило применяется к деструкторам основы и всем производным классам.

  • Перемещайте конструкторы и перемещайте операторов назначения: Если конструктор перемещения или оператор назначения перемещения выходят за исключением, невозможно гарантировать, что программа вернется к состоянию, которое она была перед операцией перемещения. Избегайте конструктора перемещения или оператора назначения перемещения, который может выйти за исключением. Задайте эти функции как noexcept поскольку стандартные функции библиотеки могут избегать операций перемещения, если они не объявлены как noexcept. Можно также объявить эти специальные функции представителей как =default. Для получения дополнительной информации о том, когда можно объявить специальные функции представителей как =default, см. AUTOSAR C++14 Rule A12-0-1.

  • Функции swap: Разработчики ожидают, что функция swap не выходит за исключением. Если функция swap выходит за исключением, стандартные алгоритмы библиотеки и операции копирования могут не работать в коде, как ожидалось. Задайте функции свопа следующим noexcept. Избегайте операций, которые могут выйти за исключением функций swap.

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

Реализация Polyspace

Polyspace® помечает определяемый пользователем деструктор, функцию деаллокации, конструктор перемещения, оператор переноса назначения и функцию свопа, если это может вызвать исключение. Если функция названа swap или Swap и принимает ссылку как вход, Polyspace рассматривает ее как функцию swap.

Polyspace игнорирует функции, которые объявлены, но не определены.

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

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

Примеры

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

В этом примере показано, как Polyspace помечает деструкторы и функции удаления, которые могут вызвать исключение. Рассмотрим этот код с двумя классами.

#include <stdexcept>
class Compliant
{
public:
	//...
	~Compliant()  //Compliant                            
	{
		try {
			// ...
			throw std::runtime_error("Error"); 
		}
		catch (std::exception& e) {
		//...	
		}
	}
};

class Noncompliant
{
public:
	//...
	~Noncompliant() 
	{
		throw std::runtime_error("Error"); //Noncompliant    
	}
	static void operator delete(void* ptr, std::size_t sz) 
	{
		// ...
		throw std::runtime_error("Error");    // Noncompliant
	}
};
  • Деструктор Compliant вызывает исключение при помощи throw оператор. Потому что это исключение обрабатывается в функции деструктора при помощи try-catch блок, ~Compliant() соответствует этому правилу.

  • Деструктор Noncompliant также вызывает исключение при помощи throw оператор. Поскольку это исключение не обрабатывается в функции, деструктор ~Noncompliant() выходы за исключением. Polyspace флаги этого throw оператор в деструкторе.

  • Функция деаллокации Noncompliant::delete() не соответствует этому правилу, поскольку не обрабатывает исключение, вызванное функцией. Polyspace помечает throw оператор в функции.

Флаги Polyspace перемещают операторов или перемещают конструкторы, если:

  • Они могут выйти за исключением

  • Они не указаны как noexcept

Рассмотрим этот код, где операции перемещения реализованы для двух классов.

#include <stdexcept>
class Compliant
{
	//...
public:
	Compliant(Compliant&& rhs) noexcept   //Compliant          
	{
		try {
			// ...
			throw std::runtime_error("Error");
		}
		catch (std::exception& e) {
			//...
		}
	}

	Compliant& operator=(Compliant&& rhs) noexcept //Compliant   
	{
		try {
			// ...
			throw std::runtime_error("Error");
		}
		catch (std::exception& e) {
			//...
		}
		return *this;
	}	
};

class Noncompliant
{
public:
	//...
	Noncompliant(Noncompliant&& rhs) //Noncompliant 
	{
		// ...
		throw std::runtime_error("Error");    //Noncompliant
	}
	Noncompliant& operator=(Noncompliant&& rhs) //Noncompliant
	{
		// ...
		throw std::runtime_error("Error");   //Noncompliant
		return *this;
	}

};

  • Оператор назначения перемещения и конструктор перемещения класса Compliant заданы как noexcept и эти функции обрабатывают исключения, которые возникают внутри них. Конструктор перемещения и оператор назначения перемещения Compliant соответствуют этому правилу.

  • Оператор назначения перемещения и конструктор перемещения класса Noncompliant не заданы как noexcept. Polyspace помечает объявление этих функций.

  • Оператор назначения перемещения и конструктор перемещения класса Noncompliant содержат throw оператор, который вызывает исключения, не обрабатывая их в рамках этих функций. Polyspace флаги эти throw операторы.

Допустим, этот код содержит две функции свопа.

#include <stdexcept>
namespace Compliant{
	class C1{};
	void Swap(C1& lhs, C1& rhs) noexcept   //Compliant
	{
		// Implementation
	}
}
namespace Noncompliant{
	class C2{};
	void Swap( C2& lhs, C2& rhs ) noexcept(false) //Noncompliant
	{
		throw std::runtime_error( "Error" );   //Noncompliant
	}
}
  • Функция Compliant::Swap() задается как noexcept и не вызывает исключения. Эта функция swap соответствует этому правилу.

  • Функция Noncompliant::Swap() задается как noexcept(false) и он выходит за исключением. Polyspace помечает спецификацию исключения функции и throw оператор.

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

Группа: Обработка исключений
Категория: Необходимый, Автоматизированный
Введенный в R2020b