AUTOSAR C++14 Rule A15-1-1

Следует выдавать только образцы типов, полученных из исключения std::

Описание

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

Выдавать следует только образцы типов, полученных из исключения std::.

Объяснение

Включение типичных объектов в качестве исключений может затруднить чтение и повторное использование кода. Рассмотрим этот код, где исключения возникают в двух разных try-catch блоки.

try{
	//..
	throw 1; // 1 means logic error;
}
catch(...){
	//...
}
//...
try{
	//...
	throw  std::logic_error{"Logic Error"};
}
catch(std::exception& e){
	//..
}
В первом кодовом блоке причина или смысл этого исключения не ясны. Неоднозначное исключение, такое как это, может затруднить чтение и повторное использование кода. Эти типы типовых исключений могут также конфликтовать за исключением, вызванными в другом месте кода, что затрудняет обработку исключений. Это указывает, что такие типовые объекты неприемлемы в качестве объектов исключений.

Во втором кодовом блоке значение и причина исключения четко сообщаются путем поднятия конкретного и уникального типа объекта в качестве исключения. Такие throw операторы также соответствуют стандартным соглашениям. Четкое информирование о намерениях разработчиков, соблюдение стандартных соглашений и выдвижение уникальных типов исключений облегчают чтение, понимание и повторное использование кода.

Класс std::exception обеспечивает последовательный интерфейс для создания уникальных исключений, соответствующих конкретным ошибкам. Стандартным соглашением является использование этого интерфейса для выдачи исключений. Чтобы сделать ваш код читаемым и переиспользуемым, поднимите объекты определенных типов, которые получают из std::exception как исключение. Типовые объекты std::exception не может быть уникальным. Такие исключения нарушают это правило.

Реализация Polyspace

  • Polyspace® флаги a throw оператор, если тип приподнятого объекта не является классом, из которого публично получают std::exception.

  • Если приподнятый объект является частью нескольких иерархий наследования, то Polyspace помечает объект, если ни один из базовых классов не выводится публично std::exception или если базовые классы не включают std::exception.

  • Если вы используете throw; оператор без аргумента в блоке catch, Polyspace не помечает throw; оператор.

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

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

Примеры

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

В этом примере показано, как Polyspace флаги throw операторы, которые поднимают объекты несовместимой иерархии классов.

#include <stdexcept>
#include <memory>

class ConventionalException : public std::logic_error{
public:
	using std::logic_error::logic_error;
};
class CustomException {};
class CustomException_derived : public CustomException {};
class PrivateDerived : private std::exception {};
class ProtectedDerived : protected std::exception {};
class MultipleInheritenceCompliant : 
	public ConventionalException, public CustomException {
public:
	MultipleInheritenceCompliant()
	: ConventionalException("Logic Error and Data Error") {
	}
};
class MultipleInheritenceNoncompliant :
	public ProtectedDerived, public CustomException {};

void Foo() {
	throw std::exception();   // Noncompliant 
	throw CustomException(); // Noncompliant
	throw CustomException_derived(); // Noncompliant 
	throw PrivateDerived();       // Noncompliant 
	throw ProtectedDerived();     // Noncompliant 
	throw MultipleInheritenceCompliant(); // Compliant
	throw MultipleInheritenceNoncompliant(); // Noncompliant
	throw ConventionalException{"Logic Error"};//Compliant
	throw std::make_shared<std::exception> // Noncompliant
	(std::logic_error("Logic Error")); 
}

  • Polyspace помечает оператор throw std::exception() потому что он поднимает типовой std::exception объект, который может не быть уникальным в коде.

  • Polyspace помечает оператор throw CustomException() потому что класс CustomException не выводится из std::exception. Polyspace помечает оператор throw CustomException_derived() по той же причине.

  • Polyspace помечает оператор throw PrivateDerived() потому что класс PrivateDerived выводит из std::exception в частном порядке. Вы не можете поймать это исключение при помощи catch(std::exception& e) блок из-за частного наследования между std::exception и PrivateDerived. Polyspace помечает оператор throw ProtectedDerived() по той же причине.

  • Polyspace помечает оператор throw MultipleInheritenceNoncompliant() потому что класс MultipleInheritenceNoncompliant не выводится публично из std::exception.

  • Polyspace помечает оператор throw std::make_shared<std::exception>(std::logic_error("Logic Error")) потому что этот оператор поднимает std::shared_ptr объект как исключение, которое не является производным от std::exception.

  • Polyspace не помечает операторы throw MultipleInheritenceCompliant() и throw ConventionalException{"Logic Error"} потому что эти операторы поднимают объекты классов, которые публично получают из std::exception.

В этом примере показано, как Polyspace флаги throw операторы в блоке catch.

#include <memory>
#include <stdexcept>
class MyException : public std::logic_error
{
public:
	using std::logic_error::logic_error;
	// Implementation
};
void catch_and_rethrow() {
	try {
		/* ... */
	}catch (std::exception e) {
		throw; // Compliant
		throw e; // Noncompliant		
	}catch (std::exception& e) {
		throw e; // Noncompliant
		throw;   // Compliant
	}catch (MyException& Error) {
		throw Error; // Compliant
	}
}
  • Пустые throw; операторы в блоках catch могут вызывать различные типы исключений в зависимости от контекста во время выполнения. Потому что Polyspace анализирует throw; операторы без какой-либо контекстно-специфической информации во время выполнения, они не могут определить, какой тип объекта является пустым throw; может возникнуть оператор. Polyspace не помечает throw; операторы в блоках catch.

  • Polyspace помечает операторы throw e потому что они поднимают std::exception e объекта как исключение. Избегайте таких throw операторы в блоках catch, которые принимают ссылки на или образцы std::exception класс.

  • Polyspace не помечает оператор throw Error поскольку он поднимает объект класса MyException который происходит от std::exception.

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

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