AUTOSAR C++14 Rule A15-5-2

Программа не должна быть резко отключена. В частности, неявный или явный вызов станд.:: аварийное прекращение работы (), станд.:: quick_exit (), станд.:: _Exit (), станд.:: оконечный () не буду сделан

Описание

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

Программа не должна быть резко отключена. В частности, неявный или явный вызов станд.:: аварийное прекращение работы (), станд.:: quick_exit (), станд.:: _Exit (), станд.:: оконечный () не буду сделан.

Объяснение

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

В зависимости от вашей среды компилятор не может высвободить выделенные средства и раскрутить стек, когда программа отключена резко, ведя к проблемам, таким как утечки памяти. Такие аварийные завершения программы могут сделать код уязвимым для атак "отказ в обслуживании". Постарайтесь не отключать программу резко.

Реализация Polyspace

Polyspace® отмечает операции, которые могут привести к резкому завершению программы. Например:

  • Деструктор класса выходит с необработанным исключением. Смотрите AUTOSAR C++14 Rule A15-5-3.

  • Конструктор глобальной переменной или статического объекта вызывается непосредственно, но это явным образом не задано как noexcept. Смотрите AUTOSAR C++14 Rule A15-2-1.

  • noexcept функционируйте повышает необработанное исключение. Смотрите AUTOSAR C++14 Rule A15-4-2.

  • Аргумент throw оператор повышает исключение. Смотрите AUTOSAR C++14 Rule M15-1-1.

  • Небезопасное завершение функционирует, такие как std::_Exit, std::abort, и std::quick_exit явным образом вызываются.

  • Функциональный std::terminate явным образом вызывается.

  • Обработчик для аварийного завершения явным образом указан при помощи функций std::set_terminate или std::get_terminate.

  • Обработчик для нормального завершения, которое указано к std::atexit повышает необработанное исключение.

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

Если вы ожидаете нарушение правила, но не видите его, относитесь, чтобы Диагностировать, Почему Кодирующие Стандартные Нарушения Не Появляются как ожидалось.

Примеры

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

В этом примере показано, как 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(...) блок.

В этом примере показано, как Polyspace отмечает выражения в throw операторы, которые могут повысить непредвиденные исключительные ситуации.

int f_throw() noexcept(false);

class WithDynamicAlloc {
public:
	WithDynamicAlloc(int n) {
		m_data = new int[n];   
	}
	~WithDynamicAlloc() {
		delete[] m_data;
	}
private:
	int* m_data;
};

class MightThrow {
public:
	MightThrow(bool b) {
		if (b) {
			throw 42;
		}
	}
};

class Base {
	virtual void bar() =0;
};
class Derived: public Base {
	void bar();
};
class UsingDerived {
public:
	UsingDerived(const Base& b) {
		m_d = 
		dynamic_cast<const Derived&>(b);
	}
private:
	Derived m_d;
};
class CopyThrows {
public:
	CopyThrows() noexcept(true);
	CopyThrows(const CopyThrows& other) noexcept(false);
};
int foo(){
	try{
		//...
		throw WithDynamicAlloc(10); //Noncompliant
		//...
		throw MightThrow(false);//Noncompliant
		throw MightThrow(true);//Noncompliant
		//...
		Derived d;
		throw  UsingDerived(d);// Noncompliant
		//... 
		throw f_throw(); //Noncompliant
		CopyThrows except;
		throw except;//Noncompliant
	}
	catch(WithDynamicAlloc& e){
		//... 
	}
	catch(MightThrow& e){
		//... 
	}
	catch(UsingDerived& e){
		//... 
	}
}

  • При построении WithDyamicAlloc объект путем вызова конструктора WithDynamicAlloc(10), исключения могут быть повышены во время динамического выделения памяти. Поскольку выражение WithDynamicAlloc(10) может повысить исключение, Polyspace отмечает throw оператор throw WithDynamicAlloc(10);

  • При построении UsingDerived объект путем вызова конструктора UsingDervide(), исключения могут быть повышены во время динамической операции кастинга. Поскольку выражение UsingDerived(d) может повысить исключения, Polyspace отмечает оператор throw UsingDerived(d).

  • В функциональном MightThrow(), исключения могут быть повышены в зависимости от входа до функции. Поскольку Polyspace анализирует функции статически, он принимает что функциональный MightThrow() может повысить исключения. Polyspace отмечает операторы throw MightThrow(false) и throw MightThrow(true).

  • В операторе throw except, объект except копируется путем неявного вызова конструктора копии класса CopyThrows. Поскольку конструктор копии задан как noexcept(false), Polyspace принимает, что операция копии может повысить исключения. Polyspace отмечает оператор throw except.

  • Поскольку функциональный f_throw() задан как noexcept(false), Polyspace принимает, что может повысить исключения. Polyspace отмечает оператор throw f_throw().

#include<cstdlib>
class obj
{
public:
	obj() noexcept(false){}
	obj(const obj& a){/*...*/}
	~obj(){/*...*/}
};
static obj staticObject;
void foo(){
	obj localObject;
	//...
	std::_Exit(-1);//Noncompliant
}
void bar(){
	obj localObject;
	//...
	std::abort;//Noncompliant
}
void foobar(){
	obj localObject;
	//...
	std::quick_exit(-1);//Noncompliant
}

В этом примере небезопасные функции завершения вызываются, чтобы отключить программу. Эти функции не выполняют существенные операции очистки, такие как вызов деструкторов. Например, деструкторы staticObject или три экземпляра localObject не вызываются. Любой ресурс, выделенный этими объектами, пропущен. Polyspace отмечает использование таких небезопасных программ завершения.

#include<cstdlib>
#include<exception>
class obj
{
public:
	obj() noexcept(false){}
	obj(const obj& a){/*...*/}
	~obj(){/*...*/}
};
static obj staticObject;

void foobar(){
	obj localObject;
	//...
	std::terminate();//Noncompliant
}

Вызов std::terminate явным образом может привести к резкому завершению программы, не вызывая деструкторы локальных и статических объектов. Polyspace отмечает явные вызовы std::terminate.

#include <stdexcept>
void atexit_handler(){//Noncompliant
	throw std::runtime_error("Error in atexit function");
}
void main(){
	try{
		//...
		std::atexit(atexit_handler);
	}catch(...){
		
	}
}

Обработчик завершения atexit_handler повышает неперехваченное исключение. Функциональный atexit_handler выполняется после основного выполнения концов. Необработанные исключения в этой функции не могут быть обработаны в другом месте, ведя к неявному вызову std::terminate(). Polyspace отмечает функцию.

#include <stdexcept>
#include <new>
class obj
{
public:
	obj() noexcept(false){}
	obj(const obj& a){
		//...
		throw -1;
	}
	~obj()
	{
		try{
			// ...
			throw std::runtime_error("Error2"); // Noncompliant
		}catch(std::bad_alloc& e){
			
		}
	}
};
obj globalObject; //Noncompliant

В этом примере, конструкторе объекта globalObject задан как noexcept. Деструктор объекта явным образом повышает необработанное исключение. Они необработанное исключение может возникнуть перед выполнением, запускаются или после main функция завершает выполнение, которое может привести к резкому и небезопасному завершению путем вызова std::abort(). Polyspace отмечает эти операции.

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

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