Why rethrow an exception - c++

In C++, why would you want to rethrow an exception. Why not let the current catch block handle the exception. For what reasons would you rethrow an exception to another try/catch block?

An exception is thrown when a function cannot meet its contract (what it promises the caller it will do). When a function calls another function that throws an exception, there are four main approaches to how it might respond:
Catch the exception and handle it. This should only be done if the function is able to meet its contract despite the exception being thrown. If it catches the exception but fails to meet its contract, it is hiding a problem from the calling code.
Allow the exception to propagate. This should be done if the exception cannot be handled by this function (that is, the function is unable to meet its contract because the exception has been thrown), and if the exception exposes the appropriate information to the calling code.
Catch the exception, do some clean-up and/or add extra info, and rethrow it. This should be done if the exception cannot be handled by this function, but it needs to do some cleaning up before propagating it. It can also provide extra information to help with handling/debugging the exception (I often think of the programmer as the very last exception handler).
Catch the exception and throw a different exception (perhaps wrapping the original). This should be done if the exception cannot be handled by this function, but a different exception better expresses the problem to the calling code.

Why not let the current catch block handle the exception. For what reasons would you rethrow an exception to another try/catch block?
The idea behind exceptions is that you throw them at the error site and handle them down the stack, where you have enough information to handle the error.
Conversely, there are cases when you must do something in case of an error, but still don't know how to handle the error (this is the case when you rethrow).
Example:
void connect_and_notify(int connection_data)
{
try
{
create_network_connection(connection_data); // defined somewhere else
notify("connection open"); // same (notify event listeners)
}
catch(const std::runtime_error&)
{
notify("connection failed");
throw;
}
}
Client code:
void terminal_app_controller()
{
try
{
connect_and_notify(1);
}
catch(const std::runtime_error& err)
{
std::cerr << "Connection failed;\n";
exit(1); // this is usually bad bad code but whatever
}
}
void ongoing_server_controller()
{
bool connected = false;
int connection = 1;
while(!connected)
{
try
{
connect_and_notify(1);
connected = true;
}
catch(const std::runtime_error&)
{
connection++;
}
}
}
In the two usage scenarios, the error is handled differently (connect_and_notify has no way of knowing that, but still, on a failed connection it must notify listeners).
Each function has a different policy to handle the exception and this means different catch blocks.

I very much dislike anything like
catch (std::exception&) {
... // do some cleanup
throw;
}
RAII is the correct solution to that problem. Even:
catch (std::exception&) {
... // do some logging here
throw;
}
can be handled with RAII, although it is less intuitive.
BUT - where I have rethrown is any situation where 3rd-part (or vendor-supplied) code throws "generic" exceptions with state. For example, when logging telematics messages to a database, I know that I often receive duplicate copies of the same message. Each message has a unique ID - so a primary key violation in my DB is an "innocent" error that should be silently ignored.
Unfortunately, the DB framework we use doesn't throw a specific exception for PK violations - so we need to catch the generic dbexception and check what its reason code is to decide what to do. Hence:
catch (db::exception& e) {
if (e.reason != db::exception::reason::pk_violation)
throw;
}
Also, piwi mentioned internal state. An example would be
for (;;) {
try {
...
}
catch (some_exception& e) {
if (retry_count > 3)
throw;
}
}
Remember: If you are going to rethrow, always catch by reference to avoid slicing the exception object. (You should usually catch by ref anyway, but it is even more important when rethrowing)

Related

Is it important that what() does not throw (exception classes)?

An exercise from C++ Primer asks
Why is it important that the what function [of exception classes] doesn’t throw?
Since there is no way to check my answer I was hoping to get an opinion. I thought possibly that it is an error (maybe terminate would've been called) to throw another exception during a catch clause (other than a rethrow throw;) while the current exception object is still being handled. It seems that is not the case though and it is completely okay to throw out of catch clauses:
#include <iostream>
using namespace std;
int main(){
try{
try{
throw exception();
} catch(exception err){ throw exception();}
} catch(exception err){ cout << "caught"} //compiles and runs fine, outputs "caught"
}
So program terminations are not a worry. It seems then, any problem that arises from what() throwing should, at the very least, be rectifiable by the user if they were so inclined.
Maybe then, the importance might be that while handling an error we do not want further unexpected errors to occur? Throws inside catch clauses are mainly intended for sending the exception object further up the call chain. A user may receive an error from deep in his program and does not want to worry that the error caught has to be associated with its own try block. Or maybe what() having its own throw may also lead to recursive effects (e.g. what() throws an exception, then we catch this exception and call what() but this then throws, and so on) meaning it might become impossible to handle any errors? How drastic can it be for what() to potentially throw?
I think there's nothing unclear - it's just as you described. If .what() method of an exception class throws an error, the whole catch effort was wasted:
try {
someDangerousOperation();
}
catch(std::exception e) {
// Ooops, instead of false,
//we get another exception totally unrelated to original error
someLogClassOrWhatever.save(e.what());
return false;
}
return true;
And Imagine the crazy code if you were expected to deal with what()'s exceptions:
try {
someDangerousOperation();
}
catch(std::exception e) {
// Not very fun
try {
someLogClassOrWhatever.save(e.what());
}
catch(...) {
alsoWhatHasFailedThatIsReallyGreat();
}
return false;
}
I think there's nothing more in that, probably the question is so simple it seems there must be some catch hiding in it. I think it's not the case.
std::exception::what() is noexcept. Consequently, if it throws, std::terminate is called. Yes, this is important.
Image a very curious coder with a slight tendency towards being a control freak (I know a couple of them myself), he really wants to know what is going wrong in his program and logs all errors with ex.what(). So he codes
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
He is pretty pleased with the world in general and with himself in particular. But now it crosses his mind, that e.what() could throw an exception as well. So he is codes:
try{
try {
code();
}
catch(std::exception &e) {
std::cout<<e.what()
}
}
catch(std::exception &e) {
std::cout<<e.what()
}
A minute later he notices, that there is again an uncaught exception possible! Remember, he is a control freak, so he is going to write another try-catch block and than another and another
So you can bet any money, his project will be late - how could you do something like this to my friend? So please make sure e.what() doesn't throw:)
I guess it is the reason behind what being noexcept.

Will throwing an exception in a catch block lead to two exceptions being in flight? [duplicate]

This question already has answers here:
Nested try...catch inside C++ exception handler?
(2 answers)
Closed 1 year ago.
Consider the following C++ code:
class MyException {};
void someFunction()
{
try
{
/// ... code that may throw
}
catch(std::exception& e )
{
throw MyException();
}
}
Question
Is the exception e absorbed at the beginnging of the catch block or at the end of the catch block?
In the second case throwing the new exception would result in having two exceptions in flight, what is not what I want. I want to absorb the std::exception and start one of my own type.
No. That's how one should do it. The throw myException() can only occur if the first exception has been caught and hence is no longer 'in flight'.
This design pattern is quite common to 'translate' error messages coming from another library that your code is using to an error that the user of your code can better relate to.
Alternatively, if you want to do more than merely throw (say you want to do some clearing up of resources -- though that should really be done via RAII, i.e. from destructors), then you can simply rethrow the original exception via
try
{
// ... code that may throw
}
catch(...) // catches anything
{
// ... code that runs before rethrowing
throw; // rethrows the original catch
}
just throw; statement is enough in catch block to rethrow same exception in higher context.
It throws SAME exception again. No new exception is generated. So no fight :)
In case you want to catch exception of type A and then throw exception of type B, then the way you did it is absolute correct.
In this case, old exception (type A) is caught(absorbed) and only new exception(type B) is thrown to higher context. So, again no fight :)

Rethrow from a function in the catch block

In this case, I have want to perform some actions based on the exception thrown and then re-throw the exception. Is this recommended - My aim is to do some work based on the exception thrown and rethrow it and have the application crash and generate dump that have the call stack in the exception.
class Foo
{
public:
void HandleException(const std::exception& ex)
{
// Log, report some metrics
throw;
}
void Work(//Some inputs)
{
try
{
// trying doing some work
}
catch (const std::exception& ex)
{
// This is really an exceptional situation, and the exception should be thrown which
// cause the exe to abort and create dump.
// Intention is to preserve call stack and have it in dump.
HandleException(ex);
}
}
}
Let me add another note to the question: When I have HandleException as a lambda function, throw in the lambda causes exception. Do I need to capture some state and how do I do that ?
When you catch an exception you have two options:
Achieve the original goal (contract) in some way, e.g. by retrying.
Report failure by throwing.
Rethrowing the original exception is one way to implement the second bullet point.
Yes that is valid. BUT it is also dangerous.
If you call throw; with no parameters and there is no exception currently in flight this will result in a call to std::terminate(). The problem with your current code is that anybody can call the function even when they are not in a catch block (which would result in termination).
So you may want to validate that an exception is propogating:
void HandleException(const std::exception& ex)
{
// Log, report some metrics
if (std::uncaught_exception()) {
throw;
}
// Maybe put an else here.
}
Also worth reading: GotW #47: Uncaught Exceptions

c++ exception handling

Learning "try & catch". What is wrong with the following code?
Thanks for the advice.
Error in execution:
terminate called without an active exception
Aborted
The code:
#include <stdio.h>
int main()
{
int a = 3;
try
{
if (a < 5)
throw;
}
catch (...)
{
printf ("captured\n");
}
return 0;
}
Your throw; statement tries to rethrow a current exception but there probably isn't one. You need something like
throw some_exception_object();
Inside of a try block, you have to specify what to throw. The only place you can use throw by itself is inside of a catch block to re-throw the current exception. If you call throw by itself without a current exception being active, you will kill your app, as you have already discovered.
Try this:
#include <stdio.h>
int main()
{
int a = 3;
try
{
if (a < 5)
throw 1; // throws an int
}
catch (...)
{
printf ("captured\n");
}
return 0;
}
You can throw anything you want, as long as you throw something.
There are four things, two major and two minor. One thing at a time...
1. Rethrow usage w/o active exception
A throw; statement is used to re-throw an exception that is currently caught. For example:
try {
do_something();
} catch (const std::exception &) {
throw; // This statement re-throws an exception that was caught in this "catch" block.
}
In your case, you are using throw; without catching any exceptions (in order words — it does not appear inside catch block directly or indirectly), thus your program is terminated. When there is a need to throw and not to re-throw an exception, like in your case, you must specify an exception object to be thrown. For example:
throw std::runtime_error("Something bad happened");
2. catch-all clause which does not re-throw a caught exception
Your catch-all clause (catch (...)) is perfectly legal C++. However, it does not re-throw caught exception. Even though it is a legal C++ code, such a usage is a taboo. C and C++ runtime is usually using special types of exceptions to implement certain functionality. For example, NPTL is using exceptions to implement a thread cancellation. If you catch that exception using catch (...), a thread won't be cancelled and you are going to have a bad time. Generally, you have to catch exceptions by their types. In almost all cases, exceptions are inherited from std::exception, and so you have to write catch (const std::exception &) or, if you expect to catch an exact type, - catch(const TypeYouExpect &). If you must, however, use catch-all, remember to re-throw. For example:
try {
do_something();
} catch (...) {
throw; // DO NOT FORGET TO RE-THROW.
}
3. Header naming...
You are including C header whereas C++ provides its own headers for standard C features. So, header:
#include <stdio.h>
.. should be:
#include <cstdio>
C++ specific C functions get special treatment. For example, they become available in std namespace. So that you can use std::open() instead of just open() or ::open(). No big deal, but is highly recommended way to go.
4. Return from main.
Unlike C, C++'s main() function is very special. It allows you not to have return 0;. This is a default behavior. So, unless you really need to return some value, you may save yourself some time by not typing return 0;. Remember, however, that main is the only function like that, and that everywhere else you must explicitly return something unless a function is marked void.
Hope it helps. Good Luck!
You need to actually throw some object. Even something as simple as
throw "error";
will catch the error like you want it to.
see it in action here
The statement to throw an exception is:
throw <expression>;
This statement:
throw;
is also called the re-throw statement and is use to re-throw an existing exception that has been caught. It is typically used in a catch block, for example, you look at the exception and decide if you can continue, retry or abort. In case you decide to abort, you re-throw the exception so that somebody else down the call stack will catch it and handle this error.
For example:
// getResult() calls can fail with a deadlock exception
// This method will retry up to 3 times before failing
Result getResultWithRetry()
{
int nbTry = 3;
for(;;) {
try {
return getResult();
} catch (DeadLockException& e) {
if (nbTry == 0) {
throw; // re-throw the deadlock exception
}
}
--nbTry;
}
}

c++ catch error raised by PPL parallel_for

I have written this piece of code to catch error launched by ppl
try
{
parallel_for (m_row_start, m_row_end + 1, [&functionEvaluation,varModel_,this](int i)
{
// do things
});
}
catch(const std::exception error_)
{
QString t(error_.what());
}
try
{
return functionEvaluation.combine(plus<double>());
}
catch(const std::exception error_)
{
QString t(error_.what());
}
No error is caught although I have strong suspicion that it does have exception raised (a larger try{}catch(...){} it catching an std::exception, with no clear message.
I am right with my syntax for catching exception raised in ppl code?
Your syntax is correct although there's no reason you couldn't catch by reference to avoid unnecessary copying of the exception object:
catch(const std::exception & error_)
Check that the exception thrown actually derives from std::exception.
The PPL will only allow exceptions to propagate once all the threads have completed, could you have a thread which is still running preventing you from seeing the exception?
For debugging purposes, you could add an extra catch block:
catch(...)
{
cout << "Unknown exception" << endl;
}
Just to check if you are getting any kind of exception thrown, however I wouldn't leave this in production code because there's no way to usefully do anything with the exception.
First, check what is thrown. If you mistype the catch, it will not react. Maybe it simply is the CONST marker? const-type is not the same as non-const-type, but I actually don't remember well if catches are const-volatile-sensitive.
Second, unless strong reasons arise, always catch by reference:
catch(std::exception& error)
If you do not, then an exception copying will occur: http://www.parashift.com/c++-faq/what-to-catch.html By copying I mean object-copying, not re-raising;)