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