MISRA C++:2008 Rule 15-1-1

Выражение присваивания оператора броска не должно самостоятельно заставлять исключение быть выданным

Описание

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

Выражение присваивания оператора броска не должно самостоятельно заставлять исключение быть выданным.

Объяснение

На C++ можно использовать throw оператор, чтобы повысить исключения явным образом. Компилятор выполняет такой throw оператор на двух шагах:

  • Во-первых, это создает аргумент для throw оператор. Компилятор может вызвать конструктора или оценить выражение присваивания, чтобы создать объект аргумента.

  • Затем это повышает созданный объект как исключение. Компилятор пытается совпадать с объектом исключения к совместимому обработчику.

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

class myException{
	myException(){
		msg = new char[10];
		//...
	}
	//...
};

foo(){
	try{
		//..
		throw myException();
	}
	catch(myException& e){
		//...
	}
}
Во время конструкции временного myException объект, new оператор может повысить bad_alloc исключение. В таком случае, throw оператор повышает bad_alloc исключение вместо myException. Поскольку myException было ожидаемое исключение, блок выгоды несовместим с bad_alloc. bad_alloc исключение становится необработанным исключением. Это может заставить программу прерываться неправильно, не раскручивая стек, ведя к утечке ресурсов и уязвимостям системы обеспечения безопасности.

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

Реализация Polyspace

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

  • Функции, которые заданы как noexcept(false)

  • Функции, которые содержат один или несколько явный throw операторы

  • Конструкторы, которые выполняют операции выделения памяти

  • Выражения, которые включают динамический кастинг

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

Если вы ожидаете нарушение правила, но не видите его, обратитесь к Кодированию Стандартных Нарушений, Не Отображенных.

Примеры

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

В этом примере показано, как 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(), исключения могут ve, повышенный в зависимости от входа до функции. Поскольку 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().

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

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