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 операторы, которые повышают тот же класс, перечисление значений, целое число или постоянный литерал как исключения, и отмечают итоговый оператор броска, которые повышают тот же объект. Вы можете хотеть повысить то же исключение в нескольких местах при помощи предварительно созданного объекта исключения. 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