Unicorn with delicious cookie
Мы используем куки, чтобы пользоваться сайтом было удобно.
Хорошо
to the top
>
>
>
V1067. Throwing from exception...
menu mobile close menu
Проверка проектов
Дополнительная информация
toggle menu Оглавление

V1067. Throwing from exception constructor may lead to unexpected behavior.

14 Окт 2020

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

Рассмотрим синтетический пример:

#include <stdexcept>

class divide_by_zero_error : public std::invalid_argument
{
public:
  divide_by_zero_error() : std::invalid_argument("divide_by_zero")
  {
    ....
    if (....)
    {
      throw std::runtime_error("oops!");   // <=
    }
  }
};

void example(int a, int b)
{
  try
  {
    if (b == 0)
      throw divide_by_zero_error ();
    ....
  }
  catch (const divide_by_zero_error &e)
  {
    ....
  }

  // my_exception thrown and unhandled
}

В коде функции 'example' программист пытается обработать возникшее исключение 'divide_by_zero_error', однако вместо этого будет сформировано исключение 'std::runtime_error' и не перехвачено последующим 'catch'-блоком. Это приведет к тому, что исключение покинет функцию 'example', что может привести к следующим ситуациям:

  • исключение будет обработано другим обработчиком исключений выше по стеку вызовов, что также может не являться желаемым поведением;
  • соответствующего обработчика исключений может не оказаться выше по стеку вызовов, и тогда программа будет аварийно завершена функцией 'std::terminate' как только исключение покинет функцию 'main'.

При разработке и использовании собственных классов исключений нужно проявлять особую бдительность, поскольку исключения в их конструкторах могут возникнуть в неожиданных местах, например при вызове других функций. В следующем примере при создании логирующего исключения может возникнуть второе исключение из функции 'Log':

#include <ios>

static void Log(const std::string& message)
{
  ....
  // std::ios_base::failure may be thrown by stream operations
  throw std::ios_base::failure("log file failure");
}

class my_logging_exception : public std::exception
{
public:
  explicit my_logging_exception(const std::string& message)
  {
    Log(message); // <=
  }
};

Данная диагностика классифицируется как: