exponenta event banner

Правило AUTOSAR C++ 14 A15-4-2

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

Описание

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

Если функция объявлена как noexcept, noexcept (истина) или 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(...) блок.

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

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