AUTOSAR C++14 Rule A15-4-2

Если функция объявлена как noexcept, noexcept (true) или noexcept (< true condition >), то она не должна выходить за исключением

Описание

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

Если функция объявлена как noexcept, noexcept (true) или noexcept (< true condition >), то она не должна выходить за исключением.

Объяснение

Можно указать, что вызываемая сущность не вызывает исключение, задав его как noexcept, или noexcept(true), или noexcept(<true condition>). Компилятор ожидает, что noexcept функция не выходит за исключением. Исходя из этого предположения, компилятор опускает процесс передачи исключения для noexcept функций. Когда noexcept функция выходит за исключением, исключение становится необработанным.

Если a noexcept функция выходит за исключением, компилятор вызывает std::terminate() неявно. Функция std::terminate() завершает выполнение программы определенным в реализации способом. То есть точный процесс завершения программы зависит от конкретного набора программного и оборудования, которое вы используете. Для образца, std:terminate() может вызвать std::abort() аномально прервать выполнение без размотки стека, что приводит к утечке ресурсов и уязвимостям безопасности.

Задайте функции следующим noexcept или noexcept(true) только когда вы знаете, что функции не вызывают исключений. Если вы не можете определить спецификацию исключения функции, задайте ее при помощи noexcept(false).

Реализация Polyspace

Если вы задаете вызываемую сущность при помощи noexcept, noexcept(true), или noexcept(<true condition>), Polyspace® проверяет вызываемую сущность на наличие необработанных исключений и помечает вызываемую сущность, если он может выйти за исключением.

Когда вызываемая сущность вызывает другие вызываемые сущности, Polyspace делает определенные предположения, чтобы вычислить, могут ли быть необработанные исключения.

  • Функции: Когда noexcept функция вызывает другую функцию, Polyspace проверяет, может ли вызываемая функция вызвать исключение, только если оно задано как noexcept(<false>). Если вызываемая функция задана как noexceptPolyspace принимает, что это не вызывает исключение. Некоторые стандартные функции библиотеки, такие как конструктор std::string, используйте указатели на функции для выполнения выделения памяти, что может вызвать исключения. Потому что эти функции не заданы как noexcept(<false>)Polyspace не помечает функцию, которая вызывает эти стандартные функции библиотеки.

  • Внешняя функция: Когда noexcept функция вызывает внешнюю функцию, Polyspace помечает объявление функции, если внешняя функция задана как noexcept(<false>).

  • Виртуальная функция: Когда функция вызывает виртуальную функцию, Polyspace помечает объявление функции, если виртуальная функция задана как noexcept(<false>) в производном классе. Для образца, если a noexcept функция вызывает виртуальную функцию, которая объявлена как noexcept(<true>) в базовом классе и noexcept(<false>) в последующем производном классе Polyspace помечает объявление noexcept функция.

  • Указатели на функцию: Когда noexcept функция вызывает указатель на функцию, Polyspace принимает, что указатель на функцию не вызывает исключений.

При анализе, вызывает ли функция необработанные исключения, Polyspace игнорирует:

  • Исключения, вызванные деструкторами

  • Исключения, высказанные в atexit() операции

Polyspace также игнорирует динамический контекст при проверке на исключения. Например, функция может вызвать необработанные исключения, которые возникают только в определенных динамических контекстах. Polyspace помечает такую функцию, даже если исключение может не быть вызвано.

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

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

Примеры

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

В этом примере показано, как Polyspace флаги noexcept функции, которые могут вызвать необработанные исключения. Рассмотрим этот код, содержащий несколько noexcept функций. Эти функции вызывают другие вызываемые сущности, такие как функции, внешние функции и виртуальные функции.

#include <stdexcept>
#include <typeinfo>
void LibraryFunc(); 
void LibraryFunc_noexcept_false() noexcept(false);  
void LibraryFunc_noexcept_true() noexcept(true);    



void SpecFalseCT() noexcept  // Noncompliant
{
	try {
		LibraryFunc_noexcept_false();
	} catch (int &e) {
		LibraryFunc_noexcept_false();  
	} catch (std::exception &e) {
	} catch (...) {
	}
}

class A {
public:
	virtual void f() {}              
};

class B : A {
public:
	virtual void f() noexcept {}     
};

class C : B {
public:
	virtual void f() noexcept {}     
};

class D : A {
public:
	virtual void f() noexcept(false) { throw(2);}
};

void A1(A &a) noexcept {          // Noncompliant
	a.f();
}

void D2(D &d) noexcept {          //Compliant
	try {
		d.f();
	} catch (int i) {
	} catch (...) {
	}
}

void B2(B *b) noexcept {          // Compliant
	b->f();
}
template <class T>
T f_tp(T a) noexcept(sizeof(T)<=4)    // Noncompliant
{
	if (sizeof(T) >4 ) {
		throw std::runtime_error("invalid case");
	}
	return a;
}
void instantiate(void)
{
	f_tp<char>(1);
}
void f() noexcept {               //Noncompliant
	throw std::runtime_error("dead code");
}

void g() noexcept {               // Compliant
	f();
}  

  • Polyspace помечает объявление шаблона функции f_tp потому что:

    • Условие sizeof(T)<=4 вычисляет, чтобы true для char таким образом шаблон становится noexcept(true) функция.

    • Polyspace анализирует noexcept(true) образец шаблона статически. Polyspace определяет, что шаблон может вызвать исключение из-за throw оператор, даже если условие sizeof(T)>4 является false. То есть Polyspace помечает шаблон, хотя throw оператор не достигается.

    Polyspace игнорирует шаблоны функций, которые не являются экземплярами.

  • Polyspace помечает noexcept функциональные SpecFaleCT() потому что эта функция вызывает noexcept(false) внешние функциональные LibraryFunc_noexcept_false() не инкапсулируя его в try-catch блок. Любые исключения, вызванные этим вызовом внешней функции, могут вызвать необработанное исключение.

  • Polyspace помечает объявление noexcept функциональные A1() потому что эта функция может вызвать noexcept(false) функциональные D.f() когда параметр входа a является классом D. В зависимости от класса входного параметра, noexcept полиморфная функция A1() может вызвать необработанное исключение.

  • Polyspace помечает функцию f() потому что это noexcept функция, которая использует throw для создания необработанного исключения. Polyspace не помечает noexcept функциональные g() хотя он и вызывает f() потому что f() задается как noexcept.

  • Polyspace не помечает noexcept функциональные D2() несмотря на то, что он вызывает noexcept(false) функциональные D.f() потому что D2() обрабатывает исключения, которые могут возникнуть при помощи catch(...) блок.

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

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