CERT C++: ERR55-CPP

Соблюдайте технические требования исключения

Описание

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

Соблюдайте технические требования исключения [1]

Реализация Polyspace

Это средство проверки проверяет на функции Noexcept, выходящие за исключением.

Примеры

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

Проблема

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

Когда noexcept сущность вызывает другие вызываемые сущности, 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 отмечает такую функцию, даже если исключение не может быть повышено.

Риск

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

Фиксация

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

Пример

Рассмотрите этот код, где две функции заданы как noexcept. Polyspace статически анализирует эти функции и функции, которые они вызывают.

#include <stdexcept>
#include <typeinfo>
bool f(bool flag){
	if(flag==true)
	throw flag;
	return flag;
	
}
void LibraryFunc_noexcept_false() noexcept(false);  
void SpecFalseCT() noexcept  // Noncompliant
{
	try {
		LibraryFunc_noexcept_false();
	} catch (int &e) {
		LibraryFunc_noexcept_false();  
	} catch (std::exception &e) {
	} catch (...) {
	}
}
bool flag = false;
void Caller() noexcept {          //Noncompliant
	try {
		if(f(flag)){
			//...
		}
	} catch (int i) {
		//...
	} 
}

  • Polyspace отмечает noexcept функциональный SpecFaleCT() потому что это вызовы функции noexcept(false) внешний функциональный LibraryFunc_noexcept_false() не обрабатывая исключений, которые могут быть повышены от него. Эти исключения могут вызвать noexcept функционируйте, чтобы выйти за исключением.

  • Polyspace отмечает noexcept функциональный Caller потому что это вызовы функции noexcept(false) функциональный f(), который содержит явный throw оператор. Даже при том, что throw оператор не выполняется когда flag false, Polyspace игнорирует динамический контекст и отмечает Caller.

Коррекция

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

#include <stdexcept>
#include <typeinfo>
bool f(bool flag){
	if(flag==true)
	throw flag;
	return flag;
	
}
void LibraryFunc_noexcept_false() noexcept(false);  
void SpecFalseCT() noexcept(false)// Compliant
{
	try {
		LibraryFunc_noexcept_false();
	} catch (int &e) {
		LibraryFunc_noexcept_false();  
	} catch (std::exception &e) {
	} catch (...) {
	}
}
bool flag = false;
void Caller() noexcept{//Noncompliant // polyspace CERT-CPP:ERR55-CPP 
//[Justified:Unset] "Exception is not thrown when flag is false"
	try {
		if(f(flag)){
			//...
		}
	} catch (int i) {
		//...
	} 
}

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

  • Функциональный f() не повышает исключение когда flag false. Функциональный Caller соблюдает его спецификацию исключения, но Polyspace отмечает его, потому что Polyspace игнорирует динамический контекст. Этот дефект выравнивается по ширине при помощи комментария.

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

Группа: 08. Исключения и обработка ошибок (ERR)
Введенный в R2020b

[1]  Это программное обеспечение было создано MathWorks, включающим фрагменты: “Веб-сайт SEI CERT-C”, © 2017 Carnegie Mellon University, веб-сайт SEI CERT-C © 2017 Carnegie Mellon University”, CERT SEI C Кодирование Стандарта – Правил для Разработки безопасных, Надежных и Защищенных систем – 2 016 Выпусков”, © 2016 Carnegie Mellon University, and “CERT SEI Стандарт Кодирования C++ – Правил для Разработки безопасных, Надежных и Защищенных систем на C++ – 2 016 Выпусков” © 2016 Carnegie Mellon University, со специальным разрешением от его Института программной инженерии.

ЛЮБОЙ МАТЕРИАЛ УНИВЕРСИТЕТА КАРНЕГИ-МЕЛЛОН И/ИЛИ ЕГО ИНСТИТУТА ПРОГРАММНОЙ ИНЖЕНЕРИИ СОДЕРЖАЛ, ЗДЕСЬ ПРЕДОСТАВЛЯЕТСЯ НА БАЗИСЕ "ASIS". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

Это программное обеспечение и сопоставленная документация не были рассмотрены, ни являются подтвержденным Университетом Карнеги-Меллон или его Институтом программной инженерии.