How to avoid writing repeated code in catch blocks? - c++

I am using QT 4.8 (C++) for desktop application project, and writing exception handling which is as follows :
void callerMethod()
{
try
{
method1();
}
catch(Exception1& e)
{
// display critcal error message
// abort application
}
catch(std::Exception& e)
{
// print exception error message
}
catch(...)
{
// print unknown exception message
}
}
void method1()
{
try
{
// some initializations
// some operations (here exceptions can occur)
// clean-up code (for successful operation i.e no exception occurred)
}
catch(Exception1& e)
{
// clean-up code
throw e;
}
catch(Exception2& e)
{
// clean-up code
throw e;
}
catch(Exception3& e)
{
// clean-up code
throw e;
}
catch(...)
{
// clean-up code
throw;
}
}
So my question do I need to write the clean-up code in every catch block?
Is there any way I can avoid writing repeated code?
NOTE:: [ In method1() ] I want to re-throw exceptions which occurred
to my caller.So I can not catch them in single catch block,
because then type information will be lost.

Method1 can be much simplified by two concepts:
RAII. Put any clean-up code into destructors, and the clean-up code will be centralized.
Use the unqualified throw, and you won't need to know about the type of exception thrown.
So, method1() should look like:
void method1()
{
// some initializations of RAII objects
// some operations (here exceptions can occur)
}
The first catch clause in callerMethod can be removed if you derive Exception1 from std::exception, since the what() method is virtual.

You should throw exceptions as low as possible and catch them as high as possible in the call chain. This automatically leads to less code duplication, and centralizes error handling. You are throwing/catching all in one place, which seems a bit ... forced.
I often do this kind of thing (especially for program-ending exceptions:
int main()
try
{
function_calls_that_may_throw();
// ...
}
catch(my_exception& e)
{
e.do_exception_stuff();
}
catch(std::exception& e)
{
std::cout << e.what();
}
catch(...)
{
std::cout << "Something bad happened.\n";
}
This is only possible for throwing exceptions you don't plan on handling better or retrying the failed operation or something.
The pro of this approach is that all/most error handling code is at the top-level of your program, and all the functions in the call chain don't have to worry one bit about this stuff, all they do is throw an exception when they feel like it.

If all your clean up code is totally identical, you can do everything in your catch (...) block:
try {
// code
} catch (...) {
// cleanup
throw;
}
If your code varies slightly, you can always call a cleanup function:
try {
// code
} catch (exc1 ex) {
cleanup(args);
// exc1 specific
throw;
} catch (exc2 ex) {
cleanup(args);
// exc2 specific
throw;
} catch (...) {
cleanup(args);
throw;
}

Related

How should I use C++ constructor exceptions?

I've never tried using C++ exceptions until a few days ago, and I'm not sure if I'm doing this right. I'm trying to throw an exception on a constructor that fails, like
X::X() {
/*...*/
if(error)
throw;
/*...*/
}
And using it like:
try {
X a;
X b;
X c;
}
catch (...) {
// error handling
}
The debugger (VS) says there's an unhanded exception on the throw. Code after throw gets executed (I though throw worked like return), and the catch block isn't executed. What am I missing here?
I may have oversimplified this post a little bit, but the original code is a bit complex to post here.
It's because you do not throw an exception object. You should use throw like this:
throw std::runtime_error("Error message");
then you'll be able to catch it via
try {
...
} catch (const std::runtime_error& e) {
/* Handling */
}
Have a look at the stdexcept header.
You should throw some exception (generally an instance of some subclass of std::exception), e.g.
X::X() {
/*...*/
if(error)
throw std::runtime_error("my bad");
/*...*/
}
See std::runtime_error for more.
throw; without any exception makes only sense inside a catch block.
I agree with Danvil's answer: throwing an exception inside a constructor is poor taste.

Nested catch operators

I need catch exceptions that are maybe thrown by code in try...catch construction, and do something depending on exception type. But also I want do some code if any exception are thrown.
I did so:
try
{
// code
}
catch (...)
{
try
{
throw;
}
catch (exc1)
{
// handling
}
catch (exc2)
{
// handling
}
// here is code that are executed if any exception are thrown
}
My code works, but I want to know whether the Standard says anything about it.
Maybe is there any better method?
UPD: Sorry for the slow answers to comments. Simple, English is a second language for me.
UPD: I think that code from AdelNick or second code from Steve Jessop or second code from David Rodríguez - dribeas are right for me.
Your approach is bad, because the // here is code that are executed if any exception are thrown part won't be executed if neither of exc1 or exc2 branch catch the exception. Your code is an equivalent version of the following:
try
{
// code
}
catch (exc1)
{
// handling
}
catch (exc2)
{
// handling
}
// here is code that are executed if any exception are thrown
The C++ language does not support a finally block, if that's what you're after. That is because an object's destructor is responsible for freeing resources, not a finally block. Here is Stroustrup's explanation of the topic.
You should write:
try
{
// code
}
catch (exc1)
{
// handling
}
catch (exc2)
{
// handling
}
catch (...)
{
// here is code that are executed if any *other* exception are thrown
}
If you want particular code to be executed as part of all three cases then you have two options: call it in all three places, or do something like this:
bool threw = true;
try
{
// code
threw = false;
}
catch (exc1)
{
// handling
}
catch (exc2)
{
// handling
}
catch (...) {
}
if (threw) {
// here is code that are executed if any exception are thrown
}
I would change the code order as following:
try
{
try
{
// code
}
catch (exc1)
{
// handling
throw; // edited. was: throw exc1;
}
catch (exc2)
{
// handling
throw; // edited. was: throw exc2;
}
}
catch(...)
{
// here is code that are executed if any exception are thrown
}
as it works if any other type of exception is thrown (not only exc1 or exc2). Also if the code common for all exceptions is the resource releasing, consider using RAII principle instead).
Looking at the comments it seems that you may be expecting something that won't happen, and that has already been discussed in other answers. But it could be a misunderstanding on our side. If the code inside the try can only throw one of exc1 or exc2 then yes, it will do what you expect.
From the comment update, it seems that the intention was to handle any exception, including those that are neither exc1 nor exc2. For that purpose, the code won't do what is expected and exc3 will propagate outside of the nested trys. Just flatten the two levels and add a catch (...) at the end.
From here on the answer was based on a false assumption about the question.
The pattern of rethrowing is supported by the standard and used commonly in situations where the handling of the exceptions in different contexts is the same to avoid code duplication:
void processException() {
// implement exception handling in all contexts
try {
throw;
} catch (exceptionType1 const & ex1) {
} catch (exceptionType2 const & ex2) {
// } catch (...) {
}
}
void f() {
try {
something();
} catch (...) {
processException();
}
}
void g() {
try {
anotherThing();
} catch (...) {
processException();
}
}
If the code to handle the exceptions is not going to be centralized for different functions, that pattern may complicate the code more than you need. You could consider a single try/catch with an extra control variable:
bool success = false;
try {
doSomething();
success = true;
} catch (exception1 const & ex1) {
...
} catch (exception2 const & ex2) {
...
// } catch (...) {
}
if (!success) {
// common code to all exceptions
}

Catch block doesn't want to catch thrown exception

I have a code:
void Engine::count(const std::set<boost::filesystem3::path>& files)
{
for (auto e : files)
{
try
{
count_(e);
}
catch (const Bad_formatting& ) // Here I'm trying to catch this exception
{//but debugger never stops on this line even though breakpoint is set
throw; // and re-throw it
}
}
}
Then there is this count_ function:
void Engine::count_(const boost::filesystem3::path& file)
{
// and somewhere along this lines I'm throwing Bad_Formatting:
if (something)
{
}
else
{
throw Bad_formatting(file,"No end of multicomment found.");
}
}
But after throwing this exception, I'm getting dialog telling me that my application requested runtime to terminate in an unusual way...
The exception is never cought. Why? Does the fact that both of those fncs are static has anything to do with it? Or the fact that I'm using Qt?
EDIT:
This is the code which calls count:
try
{
Engine::count(files);
}
catch (const Bad_formatting& e)
{
QMessageBox::warning(nullptr,"Bad Formatting",msg);
}
////
struct Bad_formatting : public std::runtime_error
{
private:
boost::filesystem3::path file_name_;
public:
Bad_formatting(boost::filesystem3::path file_name,
const char* msg):std::runtime_error(msg),
file_name_(file_name)
{
}
const boost::filesystem3::path& file_name()const
{
return file_name_;
}
~Bad_formatting()throw()
{/*eb*/}
};
From the code you show you
throw an exception;
catch it;
rethrow it;
never catch it again.
Item 4 seems to be the important part.
What compiler/toolchain/debugger are you using? If you are using GCC you can use the catch throw and catch catch commands to add breakpoints on exception throwing/catching.
As of the possible reasons that it is not being caught, if the only code in the catch block is a throw, the compiler might have optimized the whole block away. Consider adding any instruction to the block (note any might require some instruction with actual side effects, or the compiler might also optimize that away)

Will exception thrown in catch block be caught by later catch blocks?

Consider the following C++ code:
try {
throw foo(1);
} catch (foo &err) {
throw bar(2);
} catch (bar &err) {
// Will throw of bar(2) be caught here?
}
I would expect the answer is no since it is not inside the try block and I see in another question the answer is no for Java, but want to confirm C++ is also no. Yes, I can run a test program, but I'd like to know the language definition of the behavior in the remote case that my compiler has a bug.
No. Only exceptions thrown in the associated try block may be caught by a catch block.
No, It won't, An enclosing catch block upwards the hierarchy will be able to catch it.
Sample Example:
void doSomething()
{
try
{
throw foo(1);
}
catch (foo &err)
{
throw bar(2);
}
catch (bar &err)
{
// Will throw of bar(2) be caught here?
// NO It cannot & wont
}
}
int main()
{
try
{
doSomething();
}
catch(...)
{
//Catches the throw from catch handler in doSomething()
}
return 0;
}
No, a catch block handles the nearest exception, so if you try ... catch ( Exception &exc ) ... catch ( SomethingDerived &derivedExc ) the exception will be handled in the &exc block
You might achieve the desired behaviour by exception delegation to the calling method

why does throw "nothing" causes program termination?

const int MIN_NUMBER = 4;
class Temp
{
public:
Temp(int x) : X(x)
{
}
bool getX() const
{
try
{
if( X < MIN_NUMBER)
{
//By mistake throwing any specific exception was missed out
//Program terminated here
throw ;
}
}
catch (bool bTemp)
{
cout<<"catch(bool) exception";
}
catch(...)
{
cout<<"catch... exception";
}
return X;
}
private:
int X;
};
int main(int argc, char* argv[])
{
Temp *pTemp = NULL;
try
{
pTemp = new Temp(3);
int nX = pTemp->getX();
delete pTemp;
}
catch(...)
{
cout<<"cought exception";
}
cout<<"success";
return 0;
}
In above code, throw false was intended in getX() method but due to a human error(!) false was missed out. The innocent looking code crashed the application.
My question is why does program gets terminated when we throw "nothing”?
I have little understanding that throw; is basically "rethrow" and must be used in exception handler (catch). Using this concept in any other place would results into program termination then why does compiler not raise flags during compilation?
This is expected behaviour. From the C++ standard:
If no exception is presently being
handled, executing a throw-expression
with no operand calls
terminate()(15.5.1).
As to why the compiler can't diagnose this, it would take some pretty sophisticated flow analysis to do so and I guess the compiler writers would not judge it as cost-effective. C++ (and other languages) are full of possible errors that could in theory be caught by the compiler but in practice are not.
To elaborate on Neil's answer:
throw; by itself will attempt to re-raise the current exception being unwind -- if multiple are being unwound, it attempts to rethrow the most recent one. If none are being unwound, then terminate() is called to signal your program did something bogus.
As to your next question, why the compiler doesn't warn with throw; outside a catch block, is that the compiler can't tell at compile-time whether the throw; line may be executing in the context of a catch block. Consider:
// you can try executing this code on [http://codepad.org/pZv9VgiX][1]
#include <iostream>
using namespace std;
void f() {
throw 1;
}
void g() {
// will look at int and char exceptions
try {
throw;
} catch (int xyz){
cout << "caught int " << xyz << "\n";
} catch (char xyz){
cout << "caught char " << xyz << "\n";
}
}
void h() {
try {
f();
} catch (...) {
// use g as a common exception filter
g();
}
}
int main(){
try {
h();
} catch (...) {
cout << "some other exception.\n";
}
}
In this program, g() operates as an exception filter, and can be used from h() and any other function that could use this exception handling behavior. You can even imagine more complicated cases:
void attempt_recovery() {
try{
// do stuff
return;
} catch (...) {}
// throw original exception cause
throw;
}
void do_something() {
for(;;) {
try {
// do stuff
} catch (...) {
attempt_recovery();
}
}
}
Here, if an exception occurs in do_something, the recovery code will be invoked. If that recovery code succeeds, the original exception is forgotten and the task is re-attempted. If the recovery code fails, that failure is ignored and the previous failure is re-throw. This works because the throw; in attempt_recovery is invoked in the context of do_something's catch block.
From the C++ standard:
15.1 Throwing an exception
...
If no exception is presently being
handled, executing a throw-exception
with no operand calls terminate()
The reason the compiler can't reliably catch this type of error is that exception handlers can call functions/methods, so there's no way for the compiler to know whether the throw is occurring inside a catch. That's essentially a runtime thing.
I have little understanding that throw; is basically "rethrow" and must be used in exception handler (catch). Using this concept in any other place would results into program termination then why does compiler not raise flags during compilation?
Rethrowing is useful. Suppose you have a call stack three levels deep with each level adding some context resource object for the final call. Now, when you have an exception at the leaf level, you will expect some cleanup operation for whatever resources the object has created. But this is not all, the callers above the leaf may also have allocated some resources which will need to be deallocated. How do you do that? You rethrow.
However, what you have is not rethrow. It is a signal of giving up after some failed attempts to catch and process any and all exceptions that were raised.
A throw inside of a catch block with no args will re-throw the same exception that was caught, so it will be caught at a higher level.
A throw outside of a catch block with no args will cause a program termination.
To complete the previous answers with an example of when/why the compiler cannot detect the problem:
// Centralized exception processing (if it makes sense)
void processException()
{
try {
throw;
}
catch ( std::exception const & e )
{
std::cout << "Caught std::exception: " << e.what() << std::endl;
}
catch ( ... )
{
std::cout << "Caught unknown exception" << std::endl;
}
}
int main()
{
try
{
throw 1;
}
catch (...)
{
processException(); // correct, still in the catch clause
}
processException(); // terminate() no alive exception at the time of throw.
}
When compiling the function processException the compiler cannot know how and when it will be called.
You don't have anything to catch, and so the exception bubbles all the way up. Even catch(...) needs something.