Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception class copy constructor

I'm testing how throwing when doing stack unwinding calls std::terminate by having the copy constructor of the class that is used to throw, throwing.

Per C++14 N4296 - §15.1.3:

Throwing an exception copy-initializes (8.5, 12.8) a temporary object, called the exception object. The temporary is an lvalue and is used to initialize the variable declared in the matching handler (15.3).

class X
{
  public:

    X() = default;

    X(const X&)
    {
      throw std::runtime_error{"X copy constructor"};
    }
};

int main()
{
  try
  {
    throw X{};
  }
  catch(const std::exception& e)
  {
    std::cout << e.what() << std::endl; // this line gets executed, does not terminate
  }
  catch(const X& other)
  {
    std::cout << "X exception" << std::endl;
  }
}

How come the above code doesn't call std::terminate? It is my understanding of the above code that the throw X{} inside the try, starts the stack winding and then the copy constructor gets called to call the handler, but the copy constructor throws as well. As a note if change the copy constructor's throw expression for throw X{} then it terminates.

like image 251
AdvSphere Avatar asked Jun 15 '18 23:06

AdvSphere


People also ask

Can a copy constructor throw an exception?

However, the copy constructor for an exception object still must not throw an exception because compilers are not required to elide the copy constructor call in all situations, and common implementations of std::exception_ptr will call a copy constructor even if it can be elided from a throw expression.

Can a class have no copy constructor?

If no user-defined copy constructors are provided for a class type (struct, class, or union), the compiler will always declare a copy constructor as a non-explicit inline public member of its class.

What is the copy constructor of a class?

A copy constructor is a member function that initializes an object using another object of the same class. In simple terms, a constructor which creates an object by initializing it with an object of the same class, which has been created previously is known as a copy constructor.

What happens if there is no copy constructor?

Copy Constructor is called when an object is either passed by value, returned by value, or explicitly copied. If there is no copy constructor, c++ creates a default copy constructor which makes a shallow copy. If the object has no pointers to dynamically allocated memory then shallow copy will do.


1 Answers

Until the exception object has been initialized, no exception has been thrown yet. And thus, the system has not started doing exception handling.

Since the copy is throwing, and that's what initializes the exception object, the only throw that successfully executes is the one in the copy constructor.

As a note if change the copy constructor's throw expression for throw X{} then it terminates.

That's effectively a stack overflow due to infinite recursion. Each attempt to construct an exception object provokes another exception and another attempt to construct an exception object.

like image 165
Nicol Bolas Avatar answered Nov 04 '22 03:11

Nicol Bolas