Reputation: 10584
Herb Sutter in his article http://www.gotw.ca/gotw/047.htm pointed out that we cannot use uncaught_exception in desturctor function,
// Why the wrong solution is wrong
//
U::~U() {
try {
T t;
// do work
} catch( ... ) {
// clean up
}
}
If a U object is destroyed due to stack unwinding during to exception propagation, T::~T will fail to use the "code that could throw" path even though it safely could.
but I write a test program, and T::~T in fact didn't use the "code that could throw"
#include <exception>
#include <iostream>
using namespace std;
class T {
public:
~T() {
if( !std::uncaught_exception() )
{
cout<<"can throw"<<endl;
throw 1;
} else
{
cout<<"cannot throw"<<endl;
}
}
};
struct U
{
~U() {
try
{
T t;
}
catch( ... )
{
}
}
};
void f()
{
U u;
throw 2;
}
int main()
{
try
{
f();
}
catch(...)
{}
}
output is : cannot throw
did I miss something?
Thanks
Upvotes: 1
Views: 300
Reputation: 3718
This is exactly what he meant: "will fail to throw" means "will not throw because it will think that throwing isn't safe in the current context" (not "will crash"; fail here means won't happen). Because the destructor is called as part of the stack-unwinding caused by an exception std::uncaught_exception()
returns true, and T::~T()
doesn't use the code that might throw (in his words: T::~T
will fail to use the "code that could throw" path even though it safely could) because it thinks that it shouldn't throw. The point is that because T
's wrapped in a try{}catch(...){}
block it is safe to throw, even though there's a pending exception.
Upvotes: 3