What happens if I don't catch a throw? - c++

This is super basic but I can't find the answer anywhere. There's lots of posts out there about throwing and catching, but what actually happens if I throw from function1 and then call function1 from function2 but don't catch it, does that mean it just gets rethrown to the caller of function2? Judging from the following I'd say yes, but I wanted to get a solid guru-like answer before I soldier on and assume:
#include <iostream>
void function1()
{
throw 1;
}
void function2()
{
function1();
}
int main()
{
try
{
function2();
}
catch(...)
{
std::cout << "caught!";
return 0;
}
return 0;
}
Output:
caught!

Yes, that's how exceptions work. When an exception is thrown, it is caught by the topmost function in the call stack that has a handler for that exception in the scope of execution. Since you are going back to a function lower in the stack, some variables in the scope of the functions in the upper stack frames need to get out of scope, and therefore their destructors are called. This is called stack unwinding. It is really nice to combine that and RAII (lookup RAII if you don't know what that is). However, If any destructor throws an exception during stack unwinding, then it is bad and the std::terminate function will be called. Typically your program will then end (and this is why you are always advised to write non-throwing destructors).
From cppreference.com:
Once the exception object is constructed, the control flow works
backwards (up the call stack) until it reaches the start of a try
block, at which point the parameters of the associated catch blocks
are compared with the thrown expression to find a match. If no match
is found, the control flow continues to unwind the stack until the
next try block, and so on. If a match is found, the control flow jumps
to the matching catch block (the exception handler), which executes
normally.
As the control flow moves up the call stack, destructors are invoked
for all objects with automatic storage duration constructed since the
corresponding try-block was entered, in reverse order of construction.
If an exception is thrown from a constructor, destructors are called
for all fully-constructed non-static non-variant members and base
classes. This process is called stack unwinding.

Since function2() and function1() don't catch the exception it will propagate up the call stack until it is caught by the first suitable handler which you have in main(). Local objects destructors are being called along the way which is called stack unwinding. If you didn't have a suitable handler the C++ runtime would call unexpected() built-in function that would call abort() and terminate the program.

Yes, but it doesn't get "rethrown" - simply, when you throw an exception it will walk the call stack until it can find a catch block that can handle it; this is one of the most important "selling points" of exceptions.
If no suitable handler is found, std::terminate is called and your program terminates abnormally (notice that in this case it's not guaranteed that destructors will be called).

does that mean it just gets rethrown to the caller of function2?
No, it's not rethrown; the original throw sends it as far up the call stack as necessary until a handler is found. In this case, there's no handler in function1 or function2, so it ends up in the handler in main.
If it's not caught at all, and tries to leave main, then the program will terminate. (There are ways to change that behaviour, but that's not particularly relevant to this question).

Consider the following program:
#include <iostream>
void function1()
{
try
{
throw 1;
}
catch(...)
{
std::cout << "Exception caught in function1." << std::endl;
throw 1;
}
}
void function2()
{
try
{
function1();
}
catch(...)
{
std::cout << "Exception caught in function2." << std::endl;
throw 1;
}
}
int main()
{
try
{
function2();
}
catch(...)
{
std::cout << "Exception caught in main." << std::endl;
}
return 0;
}
Its output is
Exception caught in function1.
Exception caught in function2.
Exception caught in main.

You could throw without any try and catch block. For example,
std::string &someClass::operator[](unsigned position) {
// try {
if (position <= length && position >= 0) {
//return string at that position;
}else{
throw ("out of range");
}
}
In this case, the function checks if the position is within the dynamic array length. Otherwise, it throws a string which will tell the user the position they chose was out of bounds. So there are ways to use a throw statement without a try and catch block (but try and catch are used together, cannot exclude one).

Related

Throwing an exception when another exception has not been handled yet. (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

Is GotW #47 halfly wrong?

GotW #47
The Wrong Solution
"Aha," many people -- including many experts -- have said, "let's use uncaught_exception() to figure out whether we can throw or not!" And that's where the code in Question 2 comes from... it's an attempt to solve the illustrated problem:
// The wrong solution
//
T::~T() {
if( !std::uncaught_exception() ) {
// ... code that could throw ...
} else {
// ... code that won't throw ...
}
}
The idea is that "we'll use the path that could throw as long as it's safe to throw." This philosophy is wrong on two counts: first, this code doesn't do that; second (and more importantly), the philosophy itself is in error.
The Wrong Solution: Why the Code Is Unsound
One problem is that the above code won't actually work as expected in some situations. Consider:
// 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.
I believe that explanation above is completely incorrect, if std::uncaught_exception returns true it is ALWAYS unsafe to let any function including destructor to exit with another exception. Prove
If any function that is called during stack unwinding, after initialization of the exception object and before the start of the exception handler, exits with an exception, std::terminate is called. Such functions include destructors of objects with automatic storage duration whose scopes are exited, and the copy constructor of the exception object that is called (if not elided) to initialize catch-by-value arguments.
Same words in c++ (terminate is called in ~YYY()):
#include <exception>
#include <iostream>
int main(int argc, char* argv[])
{
struct YYY
{
~YYY()
{
std::cout << "during stack unwinding before throwing second exception " << std::uncaught_exception() << std::endl;
throw std::exception();
}
};
struct XXX
{
~XXX()
{
std::cout << "after first exception thrown but not catched " << std::uncaught_exception() << std::endl;
if (std::uncaught_exception())
{
try
{
YYY yyy;
}
catch (const std::exception&)
{
std::cout << "in second exception catch block " << std::uncaught_exception() << std::endl;
}
}
}
};
try
{
XXX xxx;
std::cout << "before throwing first exception " << std::uncaught_exception() << std::endl;
throw std::exception();
}
catch (const std::exception&)
{
std::cout << "in first exception catch block " << std::uncaught_exception() << std::endl;
}
std::cout << "after both exceptions catched " << std::uncaught_exception() << std::endl;
return 0;
}
My question is did I miss something and Herb Sutter is right for some specific case or he is absolutely wrong in this piece of the explanation?
It is a question of what is meant by "any function that is called during stack unwinding" in the standard text.
I believe the intent was to prevent "any function that is called directly by the stack unwinding mechanism" to terminate with an exception, i.e. to throw another (new) exception into the active stack unwinding session. This requirement is not supposed to apply to any subsequent (nested) functions calls made internally by any function that is called by the original stack unwinding session.
As long as new exceptions are thrown and caught internally, without being allowed to escape into the active stack unwinding session, they are allowed. Herb's explanation is in full agreement with the standard: it is possible to throw new exceptions during stack unwinding as long as they are intercepted and suppressed internally.
Your example calls terminate() for a different reason. You are probably compiling with post-C++11 compiler. In C++11 destructors are noexpect by default, which is why your YYY::~YYY() simply calls terminate() regardless of whether stack unwinding is in progress, or of any other external conditions (GCC will even warn you about exactly that).
Declare it as
~YYY() throw(std::exception) // or `noexcept(false)`
{
...
to test the intended behavior of the code. And no, it does not call terminate(): http://coliru.stacked-crooked.com/a/296ffb43b774409e
Herb's outdated code, obviously, suffers from the same problem.

Why is there a need for a try block before catch in exception handling c++

Is it possible to throw an exception and catch it without using a try block ?
ex:
int main()
{
throw 1;
catch(int){
std::cerr << "caught exception\n";
}
return 0;
}
According to my experience, you have to use try and catch block in a combination. Here if any error occur in the try block then only it is passed to the catch block. Thus if there is no try block then it won't know where to look for the error. Thus they need to be used in combination. I am not sure in C++ but in Java you can use catch block in singly if you extend the class to throwable.
There is a slight difference in the behavior of program control flow during an exception in flight. try-catch blocks hopefully brings the program back to the usual control flow.
When an exception is thrown at any point in the program. Normal program control flow halts. The program control flow now goes through the runtime's mechanism for exception handling. This is different from what is normal. For the normal, destructors for automatic storage always runs when control flow reaches the end of scope (lifetime) "}". For exceptions in flight, they run earlier than normal
Consider this (note the comments);
MyClass foo(){
{
MyClass c;
c.call(balhhh); //assuming this throws
// (1)
....
return c;
}
void bar(){
std::map<K,V> mp;
auto c = foo();
// (2)
mp.insert(c);
....
}
When you call bar, we can see how control flow is per-maturely leaves foo() at // (1), no other code after // (1) is executed within the scope of foo(), the same thing happens when foo() has been unwound, and we are now at // (2)
This happens throughout stack-unwinding process, And this recursively unwinds all functions... until we are back to main() where std::terminate is called.
Now, with a try-catch block, the compiler generates code that suspends that early exit behavior after program has moved to a catch block (in search for a matching handler), and if the exception is handled, control flow goes back to normal.
Consider:
MyClass foo()
try {
MyClass c;
c.call(balhhh); //assuming this throws
// (1)
....
return c;
}
catch(...){
...
}
void bar(){
std::map<K,V> mp;
auto c = foo();
// (2)
mp.insert(c);
....
}
Now, when the exception leaves, control flow leaves the norm at // (1) to search for the handler in the associated catch, if the exception was handled, the program goes back to the normal control flow. Code after // (2) will execute now...
As you can see from the explanation, try-catch blocks are the only way as dictated by C++ standards, to restore normal program control flow after an exception is thrown.
int main()
{
throw 1; //fine, program control leaves the whole of main at this point.
catch(int){ //illegal, like using an else block without an if
std::cerr << "caught exception\n";
}
return 0;
}
Even if the above code was legal, throw means control will leave the whole of the enclosing scope at the throw site.

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.