Unicorn with delicious cookie
Nous utilisons des cookies pour améliorer votre expérience de navigation. En savoir plus
Accepter
to the top
>
>
>
V1067. Throwing from exception...
menu mobile close menu
Additional information
toggle menu Contents

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

14 Oct 2020

The analyzer has detected an exception constructor that may throw another exception. Using such a class may cause the program to behave unexpectedly when handling exceptions.

Consider the following synthetic example:

#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
}

In the code of the 'example' function, the programmer intends the raised 'divide_by_zero_error' exception to be handled, but instead of it, an 'std::runtime_error' exception will be thrown, which will not be caught by the subsequent 'catch' block. As a result, the exception will leave the 'example' function, thus causing one of the following situations:

  • the exception will be handled by another exception handler higher on the call stack, which may also be an undesired behavior;
  • there could be no appropriate exception handler higher on the call stack, in which case the program will crash by calling the 'std::terminate' function as soon as the exception leaves the 'main' function.

Write and use custom exception classes with particular care because their constructors may throw exceptions at unexpected points – for example, when calling other functions. In the following example, when creating a logging exception, a second exception may be thrown by the 'Log' function:

#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); // <=
  }
};

This diagnostic is classified as: