Throwing an exception when another exception has not been handled yet. (C++) - c++

As far as I know, throwing an exception when another has not been handled yet is undefined behavior, and the program may crash. An exception is considered unhandled until it gets into the catch-block. I have the following code snippet:
#include <iostream>
using namespace std;
class ThrowingInDestructorClass
{
public:
ThrowingInDestructorClass() = default;
~ThrowingInDestructorClass() {
try {
throw std::runtime_error("2-nd exception. ");
}
catch(...)
{
std::cout << "Catched an error during Throwing class cleanup. " << std::endl;
};
}
};
void doSmth()
{
try {
ThrowingInDestructorClass throwing;
throw std::runtime_error("1-St exception. ");
}
catch(...)
{
std::cout << "Catched an error during doSmth. " << std::endl;
};
}
int main() {
doSmth();
}
Here we have a class that can throw and handle an exception inside its destructor, so it is OK. But we have a method that creates objects and throws an exception. During stack-unwinding, the class destructor will be called, throwing a 2-nd exception. So the 1-St exception will be unhandled yet.
When I run it, I get the following output:
Caught an error during Throwing class cleanup.
Caught an error during doSmth.
It may seem that everything is fine, but I'm not entirely sure that there is no UB here.
Could someone help to clarify the situation?

This answer is mostly just a summary of the comments:
I'll go through the program step by step starting at the point the first exception is thrown:
Stack unwinding begins by destroying the "throwing" object.
The destructor of the "throwing" object gets called, throwing another exception.
Stack unwinding finds a catch block for the new exception immediately, handling the exception. The destructor exits normally.
The stack unwinding finds the catch block for the first exception, handling it.
doSmth() exits normally
No function exited with an exception, thereby the condition
"...If any function that is called directly by the stack unwinding mechanism, after initialization of the exception object and before the start of the exception handler, exits with an exception, std::terminate is called. ..." en.cppreference.com/w/cpp/language/throw - Richard Critten
isn't met.
And even if you remove the try catch in the destructor, no UB will occur:
#include <iostream>
using namespace std;
class ThrowingInDestructorClass
{
public:
ThrowingInDestructorClass() = default;
~ThrowingInDestructorClass() {
throw std::runtime_error("2-nd exception. ");
}
};
void doSmth()
{
try {
ThrowingInDestructorClass throwing;
throw std::runtime_error("1-St exception. ");
}
catch(...)
{
std::cout << "Catched an error during doSmth. " << std::endl;
};
}
int main() {
doSmth();
}
This program will crash because std::terminate is called when stack unwinding (as now a function exits with an exception).
If you throw an exception when another has not been handled yet, and you let the second exception escape a destructor that was called in process of handling the first exception, then you get a well-defined program termination. –
n. 1.8e9-where's-my-share m.
Your program will crash, but that crash is not UB but well-defined behaviour

Related

Why is my exception-in-destructor not triggering std::terminate?

I am well aware of the fact that one should not throw any exception in destructor.
But as a part of making my grip on this concept,I coded this example :-
#include <iostream>
class A {
private:
int i;
public:
A() { i = 10; }
~A() { throw 30; }
};
int main(){
try{
A();
throw 10;
}
catch (int i) {
std::cout << i << std::endl;
std::cout << "exception caught" << std::endl;
}
}
As per my understanding, this program should be terminated by calling std::terminate() as there will be two exceptions at the same time. But, this program is giving the following output:-
30
exception caught
Can anyone please explain me the logic behind this as to why this is not terminating?
std::terminate will be called if an exception is thrown during stack unwinding. That means that if an exception is called while another exception is being handled, then std::terminate will be called.
In your example, that doesn't happen - A(); will construct and immediately destroy an instance of A. The throw 30 will then be caught correctly.
Changing your code to:
int main(){
try{
A a; // begin `a` lifetime
throw 10; // | throw #0
// | end `a` lifetime
// throw #1
}
catch(int i){
cout<<i<<endl;
cout<<"exception caught"<<endl;
}
}
will guarantee that std::terminate will be called. In this case, a will be destroyed and will throw while another exception is being handled.
live coliru example
Additional information:
cppreference/Destructors/Exceptions
StackOverflow: "throwing exceptions out of a destructor"
Note that in C++11 and above, your code snippet will call std::terminate and provide you a warning:
main.cpp: In destructor ‘A::~A()’:
main.cpp:16:15: warning: throw will always call terminate()
[-Wterminate]
throw 30;
^~
main.cpp:16:15: note: in C++11 destructors default to noexcept
terminate called after throwing an instance of 'int'
bash: line 7: 1505 Aborted (core dumped) ./a.out
As seen in the compiler output, since C++11 destructors are implicitly noexcept(true). If you want to prevent this behavior, you can simply mark them as noexcept(false). Example:
~A() noexcept(false)
{
throw 30;
}
live example on coliru
In your example, A() construct a temporary variable for A then destructs it immediately. Thus throw 10; is never executed.
The throw statement taking place is in the destructor for A. When executing A::~A(), the program is not unwinding (i.e. cleaning up state from an exception) at that point. See "Destructors that throw" for example.

Why C++ biased towards destructor's exception?

#include <iostream>
using namespace std;
class Cls
{
public:
~Cls()
{
throw "exp";
}
};
int main()
{
try
{
Cls c;
throw "exp";
}
catch (...)
{
cout << "Why this doesn't call" << endl;
}
}
When I execute this code, it doesn't goes in catch block. And give following exception,
But, when I run this code with little modification, it goes to catch block.
int main()
{
try
{
throw "exp";
throw "exp";
}
catch (...)
{
cout << "Why this doesn't call" << endl;
}
}
Output:
Both the above code throws 2 exception, then why Compiler is biased in destructor's case?
In the first case you first throw from the try block and then the stack unwinding throws from Cls's destructor. So you have two exceptions to be handled. C++ handles this situation by calling terminate.
Because of the peculiarity of throwing from destructors, C++11 defines that all destructors are noexcept by default. Then even if there is no other exception to be handled, the exception from a destructor will cause terminate to be called.
The second case is OK because as soon as you throw the first exception try block is left and the exception is handled in the catch block.

C++ throwing an exception from a destructor

This isn't a question on whether it's safe to throw an exception from a destructor.
http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.9 states:
"During stack unwinding, all the local objects in all those stack frames are destructed. If one of those destructors throws an exception (say it throws a Bar object), the C++ runtime system is in a no-win situation: should it ignore the Bar and end up in the } catch (Foo e) { where it was originally headed? Should it ignore the Foo and look for a } catch (Bar e) { handler? There is no good answer — either choice loses information."
IE: if during stack unwinding another exception is thrown, then the runtime system is in a no-win situation because the catch handler to 'look for' is ambiguous.
Is there an 'exception' to the above, when the exception that is thrown during stack unwinding itself is in a try/catch block? In this case there is no ambiguity:
#include <iostream>
using namespace std;
class Component
{
public:
~Component()
{
cout << "In component destructor" << endl;
try
{
throw 1;
}
catch (...)
{
cout << "Caught exception in component destructor" << endl;
}
}
};
class Container
{
public:
~Container()
{
cout << "In container destructor" << endl;
Component component;
}
}
;
int main()
{
try
{
Container cont;
throw 'a';
}
catch (...)
{
cout << "Caught main exception ok" << endl;
}
return 0;
}
The following implies it, but I was wondering if anyone knew of the relevant C++ standard sections.
http://publib.boulder.ibm.com/infocenter/comphelp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8a.doc%2Flanguage%2Fref%2Fcplr155.htm
"If during stack unwinding a destructor throws an exception and that exception is not handled, the terminate() function is called. The following example demonstrates this:"
Your Component destructor is safe. The rule you're quoting only applies if the exception is thrown out of the destructor (i.e., to the destructor's caller.)
EDIT: Here's one relevant quote from the standard (emphasis added)
Note: If a destructor called during
stack unwinding exits with an
exception, std::terminate is called
(15.5.1).

Are destructors of automatic objects invoked when terminate is called? [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
What happens when we throw from a destructor? I know that it causes terminate() to be called, and memory is indeed freed and the destructor is called, but, is this before or after throw is called from foo? Perhaps the issue here is that throw is used while the stack is unwinding that is the problem.
Is this before or after throw is called from foo?
This is what is happening:
foo() is called
An object a of type A is created on the stack
The next statement throws
Now, the dtor for a is called, which throws another exception
std::terminate is called -- which is nothing but abandoning the exception handling mechanism:
From C++0x draft:
15.5.1 The std::terminate() function
1 In the following situations exception
handling must be abandoned for less
subtle error handling techniques:
[...]
— when the destruction of
an object during stack unwinding
(15.2) exits using an exception, or
2 In such cases, std::terminate() is
called (18.7.3). In the situation
where no matching handler is found, it
is implementation-defined whether or
not the stack is unwound before
std::terminate() is called. In all
other situations, the stack shall not
be unwound before std::terminate() is
called. An implementation is not
permitted to finish stack unwinding
prematurely based on a determination
that the unwind process will
eventually cause a call to
std::terminate().
Note: Emphasis mine
Here's what happens in g++:
#include <stdio.h>
class A {
public:
~A()
{
fprintf(stderr, "in ~A\n");
throw "error";
}
};
void foo()
{
A a;
fprintf(stderr, "in foo\n");
throw "error";
}
int main()
{
try {
foo();
}
catch (const char*) {
return 1;
}
return 0;
}
[~/ecc/ellcc/ecc] main% ./a.out
in foo
in ~A
terminate called after throwing an instance of 'char const*'
Abort
[~/ecc/ellcc/ecc] main%
As you can see, the throw in foo happens first, then the throw in ~A causes the error.
You got is slightly wrong and that's why you don't understand it. You see, throw in destructor is not causing teriminate() function to be called, it is a bad practice, but it is not fatal for program execution. What is fatal is that some code throws while there's still active exception. C++ can't decide what exception to propagate further, new one or old one and it can't propagate them both. It is considered fatal for program execution and that's why terminate is called.
So, you see, without throw in foo, terminate wouldn't be called but there will be an exception thrown from ~A. So, naturally, throw in foo has to be called first and then during the second throw everything breaks.
If I'm not mistaken, once terminate is called, no (further) stack unwinding would occur.
terminate calls a handler function (which you can set with set_terminate):
The type of a handler function to be
called by terminate() when terminating
exception processing.
Required
behavior:
A terminate_handler shall terminate execution of the program
without returning to the caller.
Default behavior:
The implementation's default terminate_handler calls abort().
At least I don't know of a way to "terminate execution without returning to the caller" that would allow you to unwind the stack.
You can modify the example to see what you can expect:
#include <cstdio>
class A
{
public:
~A() {
puts("Entered A destructor");
throw "error";
}
};
void foo()
{
A a, b;
throw "error";
}
int main()
{
try {
foo();
} catch (const char*) {
return 1;
}
}
Now there are two A instances, and the destructor of the second one is never called, because the execution was terminated as soon as the destructor of the first A finished and let another exception escape.
Object a is a stack object, so there is no dynamic memory to be freed. Once control goes out of the scope of foo(), the stack frame, and therefore the object, no longer exists.
To illustrate, here's what happens in Microsoft C++:
#include <iostream>
class A {
public:
~A() {
std::cout << "in ~A" << std::endl;
throw "error";
}
};
void foo() {
A a;
std::cout << "in foo" << std::endl;
throw "error";
}
int main() {
try {
foo();
}
catch (void *) {
std::cout << "exit: 1" << std::endl;
return 1;
}
std::cout << "exit: 0" << std::endl;
return 0;
}
And the result:
>cpptest1.exe
in foo
in ~A
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.
>

Reasons for stack unwinding fail

I was debugging an application and encountered following code:
int Func()
{
try
{
CSingleLock aLock(&m_CriticalSection, TRUE);
{
//user code
}
}
catch(...)
{
//exception handling
}
return -1;
}
m_CriticalSection is CCricialSection.
I found that user code throws an exception such that m_CriticalSection is not released at all. That means due to some reasons stack is corrupted and hence unwinding failed.
My question is:
1) In what different scenarios stack unwinding can fail ?
2) what different possibility of exception can be thrown such that stack unwinding fails.
3) Can I solve this problem by putting CSingleLock outside of try block ?
Thanks,
Are you getting an abnormal program termination?
I believe your CCriticalSection object will be released CSingleLock's destructor. The destructor will get called always since this is an object on the stack. When the usercode throws, all stacks between the throw and the catch in your function will be unwound.
However, chances are that some other object in your user code or even the CSingleLock destructor has thrown another exception in the meantime. In this case the m_CriticalSection object will not get released properly and std::terminate is called and your program dies.
Here's some sample to demonstrate. Note: I am using a std::terminate handler function to notify me of the state. You can also use the std::uncaught_exception to see if there are any uncaught exceptions. There is a nice discussion and sample code on this here.
struct S {
S() { std::cout << __FUNCTION__ << std::endl; }
~S() { throw __FUNCTION__; std::cout << __FUNCTION__ << std::endl; }
};
void func() {
try {
S s;
{
throw 42;
}
} catch(int e) {
std::cout << "Exception: " << e << std::endl;
}
}
void rip() {
std::cout << " help me, O mighty Lord!\n"; // pray
}
int main() {
std::set_terminate(rip);
try {
func();
}
catch(char *se) {
std::cout << "Exception: " << se << std::endl;
}
}
Read this FAQ for clarity.
Can I solve this problem by putting CSingleLock outside of try block ?
Hard to say without having a look at the stack and error(s)/crashes. Why don't you give it a try. It may also introduce a subtle bug by hiding the real problem.
Let me start by saying that I don't know what CSingleLock and CCriticalSection do.
What I do know is that an exception thrown in your "user code" section should unwind the stack and destroy any variables that were created within the try { } block.
To my eyes, I would expect your aLock variable to be destroyed by an exception, but not m_CriticalSection. You are passing a pointer to m_CriticalSection to the aLock variable, but the m_CriticalSection object already exists, and was created elsewhere.
are you sure that lifetime of your m_CriticalSection is longer that CSingleLock?
maybe someone corrupt your stack?
3) Can I solve this problem by putting CSingleLock outside of try block ?
in this case - yes. But remember, it is not good thing for performance to put large block in mutex.
btw, catch(...) is not good practice in general. in Win32 it (catch(...)) catching SEH exceptions too, not only c++ exception. maybe you have core in this function and catch it with catch(...).
My question is:
1) In what different scenarios stack unwinding can fail ?
If exit() terminate() abort() or unexpected() are called.
With the exception of a direct calls what situations are any of these likely to happen:
An unhandeled exception is thrown. (Does not apply here)
throw an exception from a destructor while another exception is popogating
2) what different possibility of exception can be thrown such that stack unwinding fails.
Exception thrown from constructor of throw expression
Exception thrown from destructor while exception propogating.
Exception thrown that is never caught (implementatin defined if this actually unwinds stack).
Exception thrown that is not specified in exception specification.
Exception thrown across a C ABI.
Exception thrown inside a thread that is not caught (Implementation defined what happens)
3) Can I solve this problem by putting CSingleLock outside of try block ?
No. All of the above cause the application to terminate without further unwinding of the stack.