the aboving terminate reason is 'two active exception', but the following code also terminate, why? the first '~A()' throw an exception, why the second '~A()' continue?
Because exceptions unwind the stack, and cause the destruction of the rest of the (automatic) objects in scope. Which throws a second exception.
Note: throwing exceptions from a destructor is a bad idea. A destructor can never fail to destroy *this.
Note: the outer try-catch block in your first snippet is redundant.
what kind of implementation is that? Standard std::exception has no constructor taking a string
In any case, if you want to throw from a destructor (there are valid, but rare, reasons to do that), you must annotate it with noexcept(false), otherwise you get an unconditional terminate before anything else can happen
What do you mean by 'continue"? The second destructor (the destructor of a[0]) is called by the stack unwinding process initiated by the exception thrown from the first destructor (the destructor of a[1]). Because regardless of how you leave a scope, all objects local to that scope must have their destructors run.
#include <stdexcept>
#include <iostream>
#include <typeinfo>
struct A
{
~A() noexcept(false)
{
std::cout << "destructor of object at " << this << std::flush ;
if( std::uncaught_exception() )
{
std::cout << "\n (non conforming compilers like the g++-6.2 / microsoft-2015 won't get here)\n"
<< " destructor called during stack unwind, so should not throw - but throw anyway\n" << std::flush ;
throw std::domain_error( "*** this is fatal, thrown during a stack unwind" ) ; // throw anyway, if the compiler is not clang++
}
else
{
std::cout << " throws (there is no stack unwind in progress)\n" << std::flush ;
throw std::domain_error( "ha ha (no stack unwind in progress)" ) ;
}
};
};
int main()
{
std::set_terminate( [] { std::cout << "*** terminate is called ***\n" ; std::exit(1) ; } ) ;
try
{
A a[2];
std::cout << "a[0] at " << std::addressof(a[0]) << " a[1] at " << std::addressof(a[1]) << '\n'
<< "destructor of a[1] is called first, and it throws\n"
<< "stack unwind should call the destructor of a[0], which too throws\n"
<< "resulting in terminate being called\n-----------------------------------\n\n" << std::flush ;
}
catch( const std::exception& e )
{
std::cout << "caught " << typeid(e).name() << " - " << e.what() << '\n' ;
}
}
a[0] at 0x7fff18188c50 a[1] at 0x7fff18188c51
destructor of a[1] is called first, and it throws
stack unwind should call the destructor of a[0], which too throws
resulting in terminate being called
-----------------------------------
destructor of object at 0x7fff18188c51 throws (there is no stack unwind in progress)
destructor of object at 0x7fff18188c50
(non conforming compilers like the g++-6.2 / microsoft-2015 won't get here)
destructor called during stack unwind, so should not throw - but throw anyway
*** terminate is called ***
The other two compilers tested (g++-6.2 and microsoft-2015) are non-conforming; the GNU compiler does not even call terminate.
g++ (6.2):
a[0] at 0x7fffc28e6bf0 a[1] at 0x7fffc28e6bf1
destructor of a[1] is called first, and it throws
stack unwind should call the destructor of a[0], which too throws
resulting in terminate being called
-----------------------------------
destructor of object at 0x7fffc28e6bf1 throws (there is no stack unwind in progress)
caught St12domain_error - ha ha (no stack unwind in progress)
Microsoft (2015):
a[0] at 00EFFEF4 a[1] at 00EFFEF5
destructor of a[1] is called first, and it throws
stack unwind should call the destructor of a[0], which too throws
resulting in terminate being called
-----------------------------------
destructor of object at 00EFFEF5 throws (there is no stack unwind in progress)
destructor of object at 00EFFEF4 throws (there is no stack unwind in progress)
*** terminate is called ***