exponenta event banner

Правило AUTOSAR C++ 14 A15-5-1

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

Описание

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

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

Объяснение

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

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

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

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

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

Внедрение Polyspace

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

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 оператор в функции.

Полиспейс помечает операторы перемещения или конструкторы перемещения, если:

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

  • Они не указаны как 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 и не вызывает исключения. Эта функция подкачки соответствует этому правилу.

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

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

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