CERT C++: ERR58-CPP

Обработайте все исключения, выданные, прежде чем основной () начнет выполняться

Описание

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

Обработайте все исключения, выданные, прежде чем основной () начнет executing.[1]

Реализация Polyspace

Это средство проверки проверяет на Исключения, повышенные во время запуска программы.

Примеры

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

Проблема

Этот дефект происходит, когда исключение может возникнуть во время конструкции глобальных и статических переменных перед main() начинает выполняться. Если исключение повышено во время фазы запуска, вы не можете записать обработчик исключений, который компилятор может выполнить, чтобы обработать повышенное исключение. Это исключение становится необработанным исключением. Например, вы можете реализовать main() как function-try-catch блокируйтесь, чтобы обработать исключения. Ни один из catch блоки могут обработать исключения, повышенные во время фазы запуска, и эти повышенные исключения становятся необработанными исключениями.

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

  • Функция: Когда вы вызываете функцию инициализатора или конструктора непосредственно, чтобы инициализировать глобальную или статическую переменную, проверки Polyspace, повышает ли функция исключение и отмечает объявление переменной если функциональное повышение силы исключение. Polyspace выводит ли функциональное повышение силы исключение независимо от его спецификации исключения. Например, если noexcept конструктор повышает исключение, Polyspace отмечает его. Если инициализатор или конструктор вызывают другую функцию, Polyspace принимает, что вызванная функция может повысить исключение, только если это задано как noexcept(<false>). Некоторые стандартные библиотечные функции, такие как конструктор std::string, используйте указатели на функции, чтобы выполнить выделение памяти, которое может повысить исключения. Polyspace не отмечает объявление переменной, когда эти функции используются.

  • Внешняя функция: Когда вы вызываете внешние функции, чтобы инициализировать глобальную или статическую переменную, Polyspace отмечает объявление, если внешняя функция задана как noexcept(<false>).

  • Виртуальная функция: Когда вы вызываете виртуальную функцию, чтобы инициализировать глобальную или статическую переменную, Polyspace отмечает его, если виртуальная функция задана как noexcept(<false>) в любом производном классе. Например, если вы используете виртуальную функцию инициализатора, которая объявляется как noexcept(<true>) в базовом классе и noexcept(<false>) в последующем производном классе Polyspace отмечает его.

  • Указатели на функцию: Когда вы используете указатель на функцию, чтобы инициализировать глобальную или статическую переменную, Polyspace принимает, что указатель на функцию не повышает исключения.

Polyspace игнорирует:

  • Исключения повышены в деструкторах

  • Исключения повышены в atexit() операции

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

Риск

Когда исключения не обработаны, компилятор может неправильно отключить выполнение кода, не раскручивая стек в зависимости от набора аппаратного и программного обеспечения, которое вы используете. Рассмотрите этот код где конструкция статического объекта obj может вызвать исключение.

class A{
	A(){throw(0);}	
};

static A obj;

main(){
	//...
}
Статический объект obj создается путем вызова A() перед main() запускается. Когда A() повышает исключение, обработчик не может быть соответствующим за повышенным исключением. На основе набора программного и аппаратного обеспечения, которое вы используете, такое исключение может привести к завершению программы без раскручивания стека, ведя к утечке памяти и уязвимостям системы обеспечения безопасности.

Фиксация

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

Пример

Рассмотрите этот код где конструкция глобального указателя arr требует динамического выделения памяти.

#include <stdexcept>
void* alloc(size_t s) noexcept {          
	return new int[s];
}
int* arr = (int*)alloc(5);//Noncompliant
int main(){
	//..
	return 0;
}

Динамическое выделение памяти при помощи new оператор может повысить исключение. Поскольку построение arr может повысить исключение перед main() начинает выполнение, Polyspace отмечает объявление.

Коррекция

Избегайте операций, которые могут повысить исключение при построении глобальных объектов. Например, можно инициализировать глобальный указатель arr при помощи nullptr. Затем выделите память для arr в main() в try-catch блок кода.

#include <stdexcept>
#include<vector>
void* alloc(size_t s) noexcept {          
	return new int[s];
}
int* arr =nullptr;
int main(){
	try{
		arr =  (int*)alloc(5);	
	}
	catch(std::bad_alloc e){
		//..
	}
	//..
	return 0;
}

В этом случае операция динамического выделения памяти повышает std::bad_alloc исключение в main() где это может быть обработано блоками кода выгоды.

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

Группа: 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". УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИЙ НИКАКОГО ВИДА, ИЛИ ОПИСАЛ ИЛИ ПОДРАЗУМЕВАЛ, ОТНОСИТЕЛЬНО ЛЮБОГО ВОПРОСА ВКЛЮЧАЯ, НО НЕ ОГРАНИЧИЛ, ГАРАНТИЯ ПРИГОДНОСТИ ДЛЯ ЦЕЛИ ИЛИ ВЫСОКОГО СПРОСА, ИСКЛЮЧИТЕЛЬНОСТИ, ИЛИ ЗАКАНЧИВАЕТСЯ ПОЛУЧЕННЫЙ ИЗ ИСПОЛЬЗОВАНИЯ МАТЕРИАЛА. УНИВЕРСИТЕТ КАРНЕГИ-МЕЛЛОН НЕ ДАЕТ ГАРАНТИИ НИКАКОГО ВИДА ОТНОСИТЕЛЬНО СВОБОДЫ ОТ ПАТЕНТА, ТОВАРНОГО ЗНАКА ИЛИ НАРУШЕНИЯ АВТОРСКОГО ПРАВА.

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