exponenta event banner

CERT C++: ERR58-CPP

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

Описание

Определение правила

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

Реализация Polyspace

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

Примеры

расширить все

Проблема

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

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

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

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

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

[1] Это программное обеспечение было создано MathWorks, включающее фрагменты: «Сайт SEI CERT-C», © 2017 Университет Карнеги Меллон, Веб-сайт SEI CERT-C + + © 2017 Университет Карнеги Меллон, "Стандарт кодирования SEI CERT C - Правила разработки безопасных, Надежные и безопасные системы - 2016 Edition ", © 2016 Университет Карнеги Меллон, и "Стандарт кодирования SEI CERT C++ - Правила разработки безопасных, Надежные и безопасные системы в C++ - 2016 Edition "© 2016 Университет Карнеги Меллон, с специального разрешения от его Института программной инженерии.

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

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