AUTOSAR C++14 Rule A15-4-2

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

Описание

Управляйте определением

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

Объяснение

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

Если 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>). Если вызванная функция задана как noexcept, Polyspace принимает, что не повышает исключение. Некоторые стандартные библиотечные функции, такие как конструктор std::string, используйте указатели на функции, чтобы выполнить выделение памяти, которое может повысить исключения. Поскольку эти функции не заданы как noexcept(<false>), Polyspace не отмечает функцию, которая вызывает эти стандартные библиотечные функции.

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

  • Виртуальная функция: Когда вызовы функции виртуальная функция, Polyspace отмечает объявление функции, если виртуальная функция задана как noexcept(<false>) в производном классе. Например, если 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(...) блок.

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

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