exponenta event banner

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

Все создаваемые исключения должны быть уникальными

Описание

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

Все создаваемые исключения должны быть уникальными.

Объяснение

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

void f1(){
	//...
	throw std::logic_error("Error");
}
void f2(){
	//...
	throw std::logic_error("Error");
}
void f3(){
	//...
	throw std::logic_error("f3: Unexpected Condition");
}
int main(){
	try{
		f1();
		f2();
		f3();
		catch(std::logic_error& e){
			std::cout << e.what() << '\n';	
		}
	}
}
Функции f1() и f2() создать то же исключение, в то время как f3() вызывает уникальное исключение. Во время отладки невозможно определить, возникает ли исключение из f1() или f2(). Вы знаете, когда возникает исключение из f3(). Чтобы упростить процесс отладки, создайте уникальные исключения. Исключение является уникальным, если выполняется одно из следующих условий:

  • Тип исключения не встречается в другом месте проекта.

  • Сообщение об ошибке или код ошибки не появляются в другом месте проекта.

Внедрение Polyspace

Основные моменты Polyspace ®throw операторы, которые вызывают один и тот же класс, значение перечисления, целое число или постоянный литерал в качестве исключений, и помечают оператор final throw, который вызывает один и тот же объект. Можно создать одно и то же исключение в нескольких местах с помощью предварительно структурированного объекта исключения. Polyspace не помечен throw операторы, которые вызывают такие предварительно структурированные объекты исключения. Если один и тот же объект-литерал поднимается в нескольких местах, Polyspace не помечает его, если литерал не является константой или если литерал скрыт за переменной.

Поиск неисправностей

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

Примеры

развернуть все

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

#include <iostream>
#include <sstream>
#include <stdexcept>
#include <string>

int readLog();
enum ENUM {
	ENUM_VALUE_13 = 13,
	ENUM_VALUE_14 = 14,
};  
const char* value_gen(int i) {
	if (i % 2 == 0) return "value_gen-0";
	else return "value_gen-1";
}
class CustomException : public std::invalid_argument {
public:
	CustomException() : std::invalid_argument(value_gen(readLog())) {}
};
int foo0(){
	//...
		throw std::logic_error("Invalid Logic"); // Compliant
	//...
		throw std::runtime_error("Runtime Error"); // Compliant
}
int foo1(){
	//...
		throw std::logic_error(value_gen(0)); 
	//...
		throw std::logic_error(value_gen(2));  
}
int foo2(){
//..
		throw CustomException();
//..
		throw CustomException(); // Noncompliant
}

	int foo3(){
	const int localConstInt42 = 42;
	//..
		throw 42;
	//...
		throw localConstInt42; //Noncompliant
}
int foo4(){
	//..
		throw "RUNTIME_ERROR"; 
	//...
		throw "RUNTIME_ERROR"; // Noncompliant
}
int foo5(){
	//...
		throw ENUM_VALUE_14;
	//...
		throw ENUM_VALUE_14; // Noncompliant
}

  • Функция foo0() вызывает два различных типа объектов в качестве исключений. Polyspace не помечает throw операторы в foo0().

  • Функция foo1() вызывает два исключения, которые оценивают как один и тот же объект во время выполнения. Поскольку Polyspace анализирует объекты-исключения без информации о времени выполнения, исключения становятся уникальными, и оператор Polyspace не помечает инструкции throw.

  • Функция foo2() вызывает два исключения, которые оценивают как различные объекты во время выполнения. Поскольку Polyspace анализирует объекты исключений без информации о времени выполнения, исключения выглядят неуникальными. Polyspace выделяет операторы броска в foo2() и помечает окончательное заявление о броске.

  • Функция foo3() создает три исключения при использовании одинаковых объектов во время компиляции. Polyspace выделяет операторы броска в foo3() и помечает окончательное заявление о броске. По той же причине финал throw операторы в foo4() и foo5() помечены.

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

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