Noexcept function exits with exception

Функции, заданные как noexcept, noexcept(true) или noexcept(<true condition>) выходы за исключением, которое вызывает аварийное завершение выполнения программы, ведя к утечке ресурсов и уязвимости системы обеспечения безопасности

Описание

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

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

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

Риск

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

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

Фиксация

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

Примеры

развернуть все

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



void SpecFalseCT() noexcept 
{
	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 {         
	a.f();
}

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

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

void g() noexcept {               
	f();
}  

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

  • Polyspace отмечает объявление шаблона функции f_tp даже при том, что throw оператор не достигнут, потому что Polyspace игнорирует динамический контекст. Polyspace также анализирует только инстанцированные шаблоны в вашем коде. Например, если f_tp не инстанцирован в функциональном instantiate(), 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(...) блок.

Коррекция – задает функции как noexcept(false)

Можно изменить код так, чтобы функции, которые могут выйти за исключением, были заданы как noexcept(false). Такие функции могут выйти с, исключения, неправильно не отключая программу и этот дефект не повышены.

#include <stdexcept>
#include <typeinfo>
void LibraryFunc_noexcept_false() noexcept(false);
void SpecFalseCT() noexcept(false) 
{
	try {
		LibraryFunc_noexcept_false();
	} catch (int &e) {
		LibraryFunc_noexcept_false();  
	} catch (std::exception &e) {
	} catch (...) {
	}
}

Функциональный SpecFalseCT() использует внешнюю функцию, которая задана как noexcept(false). Функциональный SpecFalseCT() задан как noexcept(false) потому что это может выйти за исключением. Эта функция не повышает дефект.

Коррекция – обрабатывает исключения в noexcept Функции

Можно изменить код так, чтобы исключения были обработаны в noexcept функция. Если повышенные исключения и обработанный в функции, то noexcept функция не выходит за исключением, и этот дефект не повышен.

#include <stdexcept>
#include <typeinfo>

void f() noexcept(false) { 
throw(2);
}
void CallerFunc() noexcept {          
	try {
		f();
	} catch (int i) {
	} catch (...) {
	}
}

noexcept функциональный CallerFunc() вызовы f() который может повысить исключения. CallerFunc() имеет обработчики, чтобы обработать исключения, которые могут быть повышены и не выходят за исключением. Это функционирует, не повышает дефект.

Коррекция – выравнивает по ширине дефекты Используя комментарии

Можно выровнять по ширине повышенные дефекты с помощью комментариев: Поскольку Polyspace анализирует функции статически, он может повысить этот дефект, чтобы отметить исключения, которые находятся в мертвом коде. Используйте комментарии, чтобы выровнять по ширине дефекты, если вы думаете, что исключение не может быть повышено.

#include <stdexcept>
#include <typeinfo>
void MightThrow(unsigned int input) noexcept{// polyspace DEFECT:NOEXCEPT_FUNCTION_THROWS [Justified:Unset] "Throw in dead code"
	if(input<0)
		throw 1;
	//..
	
}

noexcept функциональный MightThrow() выходы за исключением в динамическом контексте, который не может возникнуть. Например, unsigned int вход является неотрицательным и throw оператор не выполняется. Поскольку Polyspace анализирует функции статически, он повышает дефект на throw оператор. Выровняйте по ширине дефект с помощью комментария. Результаты SeeAddress Polyspace Через Исправления ошибок или Выравнивания

Информация о результате

Группа: исключение C++
Язык: C++
Значение по умолчанию: На для рукописного кода, прочь для сгенерированного кода
Синтаксис командной строки: NOEXCEPT_FUNCTION_THROWS
Удар: высоко
Введенный в R2020b