exponenta event banner

Правило AUTOSAR C++ 14 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 ® 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