[cxx-abi-dev] Details missing for EH 2.4.1 Overview of Throw Processing

Dennis Handly dhandly at cup.hp.com
Fri Dec 16 07:28:23 UTC 2011


I'm trying to see how the code for a throw is generated and to see if
our compiler is compliant on various exception cases.

2.4.1 Overview of Throw Processing

  # Evaluate the thrown expression, and copy it into the buffer returned
  by __cxa_allocate_exception, possibly using a copy constructor.  If
  evaluation of the thrown expression exits by throwing an exception, that
  exception will propagate instead of the expression itself.  Cleanup code
  must ensure that __cxa_free_exception is called on the just allocated
  exception object.  (If the copy constructor itself exits by throwing an
  exception, terminate() is called.)

Does the last sentence mean that if there is a catch for what the copy
constructor is throwing, it is ignored?

15.5.1 terminate function:
footnote 134): ... if that copy constructor exits with an exception during
a throw.


Changing the example to throw something of class XX so we can get a
throw while evaluating the thrown expression and another during the
copy construction:

	// Allocate -- never throws:
	temp1 = __cxa_allocate_exception(sizeof(XX));

	// Construct the exception object:
try {
	#if COPY_ELISION
	  [evaluate XX() into temp1]
	#else
	  [evaluate XX() into temp2]
     try {
	  copy-constructor(temp1, temp2)
     } catch(...) {
	  // Landing Pad if this throws
	__cxa_free_exception(temp1) // never throws
        std::terminate();
     }
	#endif

	// Pass the exception object to unwind library:
	__cxa_throw(temp1, type_info<X>, destructor<X>); // Never returns
} catch(...) {

	// Landing pad for throw expression
	L1: __cxa_free_exception(temp1) // never throws

    throw;
}

Where an internal try around the copy-constructor is used to free the
exception and also always call terminate?
(Or ignore the free and just terminate?)


2.4.3 Throwing the Exception Object

  ...  _Unwind_RaiseException may return.  In that case, __cxa_throw will
  call terminate, assuming that there was no handler for the exception.

There is nothing here that indicates that __cxa_throw must call
__cxa_begin_catch before calling terminate.

This is mentioned in 2.5.3 Exception Handlers:
  When the personality routine encounters a termination condition, it will
  call __cxa_begin_catch() to mark the exception as handled and then call
  terminate(), which shall not return to its caller.

But we can't depend on the personality routine to do this because it has no
idea the unwinder can't find a handler so it seems this must also be done
in __cxa_throw.

g++ 4.6.0 seems to do this.  It seems the ABI should mention this at the
end of 2.4.3.



More information about the cxx-abi-dev mailing list