How to declare a variable in Try and access it in Catch? - c++

I am creating an object of my class in try/catch block and want to access it in catch block in case of exception. Even if the object is created ok, I cannot access it in catch block as it declared outside the block.
try {
MyObject ob(arg1,arg2); //this can trow exception
ob.func1(); //this also can throw exception
} catch (std::exception& ex){
//I want to access ob here if it was constructed properly and get the reason why func1() failed
}
I can use nested try/catch blocks to solve this issue but is there any other way to solve this
try {
MyObject ob(arg1,arg2); //this can trow exception
try {
ob.func1(); //this also can throw exception
} catch(std::exception& ex) {
//object was constructed ok, so I can access reason/state why the operation failed
}
} catch (std::exception& ex){
//object failed to construct
}

No, you can not do this. It is not possible to access this variable from same-level catch block.
The solution is to stop using exceptions as a flow control mechanism - they are not - and use them as they are, an indication of exceptional situation - in which case it doesn't really matter what did throw.

No, you cannot access an object out of scope. But to answer this:
get the reason why func1() failed
If the object construction failed because of an exception, this means that the std::exception already contains some information about why it has failed.
So you have to do this in your code:
catch (std::exception& ex){
// object failed to construct
std::cout << ex.what() << std::endl;
}

Andrei Alexandrescu's ScopeGuard might help here:
try {
MyObject ob(arg1,arg2);
SCOPE_FAIL { /* Handler 1 */ };
ob.func1();
} catch (std::exception& ex) {
/* Handler 2 */
}
The body of SCOPE_FAIL will be executed if its scope is left via stack unwinding, that is, an exception has been thrown. Unfortunately you can't access the exception itself there, but you can access ob.
The rest of the program behaves as usual, so the execution looks like:
ob is successfully constructed;
ob.func1() is executed and throws;
/* Handler 1 */ is executed;
ob is destructed;
/* Handler 2 */ is executed.

Related

C++ nested try-catch catching the same exceptions - how should I rewrite this code?

I currently have code in C++ 14 that looks like this:
try {
// create objects, process input
myObject obj; // may throw std::invalid_argument in constructor
for (i = 0; i < n_files; i++)
{
try {
process_file(); // may throw std::invalid_argument and std::runtime_error()
}
catch (std::exception& e)
{// print error
continue;
}
}
catch (std::exception& e)
{// print error
return 0;
}
For my own functions, I'm just throwing std exceptions like std::runtime_error and std__invalid_exception.
The idea is that, objects created in the outer try block should throw exceptions and be caught by the outer catch block, which would then end the program. Exceptions thrown by process_file() would be caught by the inner try block, which would just print some error but not result in program termination, and the program would continue onto processing the next file.
The outer try block contains object constructor calls that would then be used in inner try-catch, so I can't simply move it to its own try-catch otherwise the objects would be undefined in the loop.
But this code as is won't work from what I understand, because exceptions thrown in the outer try block would hit the inner catch statement first, as that is the first catch statement reachable in the code. Also, nested try-catch like this would be bad form/confusing to read from what I've read.
What would be the proper way of doing this instead?
Thanks!
this code as is won't work from what I understand
Yes, it will work just fine, for the scenario you have described.
exceptions thrown in the outer try block would hit the inner catch statement first, as that is the first catch statement reachable in the code.
That is not correct. It is not about the order in code, but the order in scope. The inner try is not in scope if the outer try throws. The exception goes up the call stack, starting at the current scope, then its nearest outer scope, then the next outer scope, and so on, until it finds a matching catch. For example:
try {
// if any std exception is thrown here, jumps to A below...
try {
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
for (int i = 0; i < n_files; ++i)
{
try {
// if any std exception is thrown here, jumps to C below...
}
catch (std::exception& e) // C
{
// print error
continue;
}
}
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
}
catch (invalid_argument& e) // B
{
// print error
return 0;
}
}
catch (exception& e) // A
{
// print error
return 0;
}
nested try-catch like this would be bad form/confusing to read from what I've read.
That is also not correct. There is nothing wrong with using nested try blocks.
However, in this example, it would make more sense to have the inner try catch ONLY std::invalid_argument and std::runtime_error specifically, since those are the 2 types it is expecting and willing to ignore to continue the loop. Don't catch std::exception generally at that spot. That way, if process_file() throws something unexpected (say std::bad_alloc, for instance), then the outer catch should handle it to terminate the process.
try {
// if any std exception is thrown here, jumps to A below...
try {
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
for (int i = 0; i < n_files; ++i)
{
try {
// if std::invalid_argument is thrown here, jumps to D below...
// if std::runtime_error is thrown here, jumps to C below...
// if any other std exception is thrown here, jumps to A below...
}
catch (std::invalid_argument& e) // D
{
// print error
continue;
}
catch (std::runtime_error& e) // C
{
// print error
continue;
}
}
// if std::invalid_argument is thrown here, jumps to B below...
// if any other std exception is thrown here, jumps to A below...
}
catch (invalid_argument& e) // B
{
// print error
return 0;
}
}
catch (exception& e) // A
{
// print error
return 0;
}
The best way to design a catch is to have it catch only the specific types of exceptions it knows how to handle at that spot in the code. Let an outer catch handle everything else. If an exception is thrown and no matching catch is found to handle it, the process will terminate by default.

Why rethrow an exception

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)

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

How to avoid writing repeated code in catch blocks?

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;
}

C++ try / catch (new to programming and not much info about this clause)

I am new to programming and am having trouble with try / catch clauses.
Here is an example from a textbook that I have:
int main( )
{
char *ptr;
try {
ptr = new char[ 1000000000 ];
}
catch( … ) {
cout << "Too many elements" << endl;
}
return 0;
}
I have tried to look online for a further explanation and the textbook does not exactly tell me what what these clauses actually do or what it is used for.
Any information would be helpful.
EDIT: The textbook I am using is:
C++: Classes and Data Structures by Jeffrey Childs
A try-catch is the C++ construct for exception handling. Google 'C++ exceptions'.
Try catch is a way of handling exceptions:
try
{
// Do work in here
// If any exceptions are generated then the code in here is stopped.
// and a jump is made to the catch block.
// to see if the exception can be handled.
// An exception is generated when somebody uses throw.
// Either you or one of the functions you call.
// In your case new can throw std::bad_alloc
// Which is derived from std::runtime_error which is derived from std::exception
}
// CATCH BLOCK HERE.
The catch block is where you define what exceptions you want to handle.
// CATCH BLOCK
catch(MyException const& e)
{
// Correct a MyException
}
catch(std::exception const& e)
{
// Correct a std::exception
// For example this would cat any exception derived from std::exception
}
You can have as many catch blocks as you like. If you exception matches any of the catch expressions in the catch statement then the associated block of code is executed. If no catch expressions matches an exception then the stack is unwound until it finds a higher level catch block and the processes is repeated (this can cause the application to exit if no matching catch block is found).
Note: If multiple catch expressions match then the lexically first one is used. Only one or none of the catch blocks will be executed. If none then the compiler will look for a higher level try/catch.
There is also a catch anything clause
catch(...)
{
// This is a catch all.
// If the exception is not listed above this will catch any exception.
}
So how does this apply to your code.
int main( )
{
char *ptr;
try
{
// This calls ::new() which can potentially throw std::bad_alloc
// If this happens then it will look for a catch block.
ptr = new char[ 1000000000 ];
// If the ::new() works then nothing happens and you pointer `ptr`
// is valid and code continues to execute.
}
catch( … )
{
// You only have one catch block that catches everything.
// So if there are any statements that generate an exception this will catch
// the excetption and execute this code.
cout << "Too many elements" << endl;
}
// As you have caught all exceptions the code will continue from here.
// Either after the try block finishes successfully or
// After an exception has been handled by the catch block.
return 0;
}
Try-catch blocks are used to trap errors in the code.
At the most basic level, errors occur because the program tries to execute an invalid instruction. That instruction (read: line of code) could be invalid for a number of reasons. In your specific instance, the instruction could be invalid if your program was not able to allocate 1,000,000,000 bytes of memory to story your ptr. The most common exception is trying to access a bad pointer, which is called a Null Pointer Exception, which occurs when you try to perform some action on an Object that either has not been created, or has been deleted (or got corrupt). You will learn to hate that exception.
Using catch(...) tells the program to execute the code inside the catch block if any error occurs inside the code within the try block. There you can handle your error and try to find someway to either fix the error condition or gracefully exit that module.
You can also catch specific errors, which you can find out more about here : http://www.cplusplus.com/doc/tutorial/exceptions/
If you already know C, try/catch achieves the same thing as setjmp/longjmp when used for error handling. Think of try as code for the if condition of setjmp and catch code for else of setjmp. This makes longjmp equivalent to throw in C++, which is used to throw an exception. In your example, probably, the new operator, which calls some memory allocation function internally, throws an exception on seeing a very large number as input by using the C++ throw operator.
void a()
{
.......
longjmp(buf,1); // <--- similar to throw
.......
}
if ( !setjmp(buf) ) // <--- similar to try
{
.......
a();
.......
}
else // <--- similar to catch
{
.......
}
try/catch is a bit more sophisticated than setjmp/longjmp, as for setjmp/longjmp you will need to declare variables which are modified in between setjmp/longjmp calls as volatile, which is not necessary for try/catch.