-
August 26th, 2014, 04:16 PM
#1
A question regarding throwing an exception
Here is the code,
Code:
class A
{
public:
~A()
{
throw 1;
}
};
int main()
{
try
{
A a;
throw 2;
}
catch(...)
{
}
}
The program ends up being terminated. Is it because catch(...) couldn't handle two exceptions? Thanks.
-
August 27th, 2014, 12:37 AM
#2
Re: A question regarding throwing an exception
Read: GotW #47: Uncaught Exceptions. Basically, you should not be throwing an exception from within a destructor.
-
August 27th, 2014, 07:42 AM
#3
Re: A question regarding throwing an exception
that isn't entirely correct.
1) you can throw exceptions from a destructor as long as they are caught in that destructor.
2) the code in your destructor can call other code which can call other code (etc.) that can throw an exception. Which is ok, as long as you catch the exception in the destructor itself.
You cannot however allow an exception to remain uncaught and try to 'terminate' the destructor. That'll cause all sorts of weird things to happen including summoning the 4 horsemen to end the world as we know it.
-
August 27th, 2014, 07:52 AM
#4
Re: A question regarding throwing an exception
Also the GotW#47 is somewhat erroneous.
There's nothing necessarily wrong in testing std::uncaught_exception() and having an if/else branch depending on the result. It is wrong if you're doing it to decide "is it safe to throw and let the throw escape the destructor", that's just ALWAYS wrong, regardless of the result of uncaught_exception.
There might be a good reason to do something else in a destructor if there's uncaught exceptions (can't think of anything useful atm). So the initial premise of the gotw is wrong or rather, confusing at least.
uncaught exceptions originating in the destructor 'escaping' the destructor is bad.
uncaught exceptions from elsewhere causing stack unwinds and destructors being called is normal case scenario, and testing for such uncaught exceptions in a destructor isn't necessarily wrong or problematic. Whether you can ever do something right/usefull is another matter entirely. I can't think of anything atm, but that doesn't mean there isn't a use.
-
August 27th, 2014, 10:15 AM
#5
Re: A question regarding throwing an exception
Originally Posted by OReubens
1) you can throw exceptions from a destructor as long as they are caught in that destructor.
True. However, if you are throwing exceptions from a destructor in order to catch it in that destructor, then you are probably misusing exceptions.
Originally Posted by OReubens
2) the code in your destructor can call other code which can call other code (etc.) that can throw an exception. Which is ok, as long as you catch the exception in the destructor itself.
Yes. This is mentioned in the article.
-
August 27th, 2014, 10:37 AM
#6
Re: A question regarding throwing an exception
Originally Posted by OReubens
that isn't entirely correct.
1) you can throw exceptions from a destructor as long as they are caught in that destructor.
2) the code in your destructor can call other code which can call other code (etc.) that can throw an exception. Which is ok, as long as you catch the exception in the destructor itself.
You cannot however allow an exception to remain uncaught and try to 'terminate' the destructor. That'll cause all sorts of weird things to happen including summoning the 4 horsemen to end the world as we know it.
Basically if an exception is not caught, then the program will be terminated. The statement catch(...) will catch "throw 1" and "throw 2", right? So home come the program is still terminated. Thanks.
-
August 27th, 2014, 10:43 AM
#7
Re: A question regarding throwing an exception
Originally Posted by LarryChen
The statement catch(...) will catch "throw 1" and "throw 2", right? So home come the program is still terminated.
It only catches the exception thrown at throw 1. When that happens, the destructor is invoked, causing the exception from throw 1 to be thrown and not caught.
-
August 27th, 2014, 11:01 AM
#8
Re: A question regarding throwing an exception
because it is throwing from the A destructor. You aren't given a means to catch something that is thrown in a destructor, so the throw 1 never arrives in the catch (...) in main.
-
August 27th, 2014, 11:33 AM
#9
Re: A question regarding throwing an exception
Originally Posted by OReubens
because it is throwing from the A destructor. You aren't given a means to catch something that is thrown in a destructor, so the throw 1 never arrives in the catch (...) in main.
But if I comment out “throw 2", "throw 1" can arrive in the catch(...) in the main. Only if I uncomment out "throw 2", "throw 1" never arrives in the catch(...). Why? Thanks.
-
August 27th, 2014, 11:37 AM
#10
Re: A question regarding throwing an exception
Originally Posted by laserlight
It only catches the exception thrown at throw 1. When that happens, the destructor is invoked, causing the exception from throw 1 to be thrown and not caught.
I don't quite understand what you said. You said it only catches "throw 1" and then you said "causing the exception from throw 1 to be thrown and not caught". What does that mean? Thanks.
-
August 27th, 2014, 12:28 PM
#11
Re: A question regarding throwing an exception
Originally Posted by LarryChen
But if I comment out “throw 2", "throw 1" can arrive in the catch(...) in the main. Only if I uncomment out "throw 2", "throw 1" never arrives in the catch(...). Why?
If you comment out the throw 2, then when the lifetime of A ends because it goes out of scope, its destructor is invoked, leading to throw 1, which is then caught.
Originally Posted by LarryChen
I don't quite understand what you said. You said it only catches "throw 1" and then you said "causing the exception from throw 1 to be thrown and not caught". What does that mean?
Sorry, typo error. It should read: It only catches the exception thrown at throw 2. When that happens, the destructor is invoked, causing the exception from throw 1 to be thrown and not caught.
-
August 27th, 2014, 12:40 PM
#12
Re: A question regarding throwing an exception
Originally Posted by LarryChen
What does that mean? Thanks.
let's rephrase it,
when an exception is thrown, living automatic (ie stack) objects are destroyed in reverse order ( in a process called "stack unwinding" ); if an exception is thrown from a destructor while stack unwinding then std::terminate is invoked.
Why ? because the language says so
ok, but why ? stack unwinding it's like an emergency plan for when something goes wrong; in theory, there could be an emergency plan for when even that emergency plan goes wrong, and so on ... so, again in theory, the language could allow multiple stack "unwindings" always allowing to rethrow from a destructor. But, this is probably not allowed because it would be too hard to follow/manage/mantain such failure scenarios ( including an infinite throw-loop ) without any true added benefit.
-
August 27th, 2014, 04:24 PM
#13
Re: A question regarding throwing an exception
Originally Posted by superbonzo
let's rephrase it,
when an exception is thrown, living automatic (ie stack) objects are destroyed in reverse order ( in a process called "stack unwinding" ); if an exception is thrown from a destructor while stack unwinding then std::terminate is invoked.
Why ? because the language says so
ok, but why ? stack unwinding it's like an emergency plan for when something goes wrong; in theory, there could be an emergency plan for when even that emergency plan goes wrong, and so on ... so, again in theory, the language could allow multiple stack "unwindings" always allowing to rethrow from a destructor. But, this is probably not allowed because it would be too hard to follow/manage/mantain such failure scenarios ( including an infinite throw-loop ) without any true added benefit.
Thanks for your reply. I think I understand it. So what happens in the code is that when "throw 2" is executed, then catch(...) will be called right away and then destroy all the automatic objects from A a until the try statement. So A's destructor will be invoked, but ”throw 1" is not caught. So the program is terminated. So the good practice is that always catch the exception thrown by the destructor within the destructor, right?
-
August 27th, 2014, 08:33 PM
#14
Re: A question regarding throwing an exception
Originally Posted by LarryChen
So the good practice is that always catch the exception thrown by the destructor within the destructor, right?
It isn't just a "good practice". You cannot allow exceptions to leave a destructor, period. Therefore you have no choice but to catch anything before the destructor completes.
-
August 28th, 2014, 06:49 AM
#15
Re: A question regarding throwing an exception
Allowing an exception to go uncaught from a destructor is "undefined behaviour" in C++.
It might seem to work... sometimes, and fail at other times, under different case scenarios.
What you are seeing is a manifestation of that undefined behaviour.
Whenever you use something in C++ that is labeled as "undefined", then the results will be undefined, non portable, may fail depending on compiler, compiler settings, operating systems, the time of day, the color of your underwear and what you mom had for breakfast 2 weeks ago.
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|