AUTOSAR C++14 Rule 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 не помечает операторы выдачи.

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

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

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

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