ПроблемаЭтот дефект происходит когда 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 игнорирует:
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 игнорирует динамический контекст. Этот дефект выравнивается по ширине при помощи комментария.