if I have a try catch block in my code, and the functions within the catch block generates an exception, what happens to that exception?
there's nothing special about throwing from a catch clause.
generally, if the catch clause is only used for some local cleanup then it's a good idea and good general programming practice to rethrow the current exception from the catch clause, and that's what the throw without argument is for.
throwing from a destructor, on the other hand, is generally problematic, because a destructor might be invoked automatically during stack unwinding (this then terminates the program).
Related
What I mean is something like this:
//std::once_flag eptrFlag;
//std::exception_ptr eptr;
//...
try
{
// may throw exceptions
}
catch (...)
{
std::call_once(eptrFlag,
[&]()
{
//...
eptr = std::current_exception();
});
}
Is this undefined behavior, or is it safe?
I've read cppreferences that say:
If called during exception handling (typically, in a catch clause), captures the current exception object
I'm not sure what is during exception handling except a normal catch clause, does the closure of the catch block count as during exception handling?
Firstly, calling std::current_exception never causes undefined behaviour.
As for what is during exception handling, actually in the language standard exception handling also includes handling an uncaught exception (for instance, 18.1(7) of C++17 standard); for std::current_exception the actual condition is “during handling by an active handler an exception”;
An exception handler is active after its catch-clause argument is initialized and until the catch clause argument has just been destroyed.
If there is not currently handled by an active handler an exception, std:current_exception will return an empty std::exception_ptr.
Calling functions does not interrupt handling, but it is possible that handing by an active handler another exception will overlap the previous one.
As for, does the lambda function capturing context of the catch block count as during exception handling - in C++ for a lambda function it would be a matter of run-time conditions, it depends on when the function is called, after the handler is complete of before; in you case it is always before; if would called after, std:current_exception would return an empty std::exception_ptr.
As for using std::call_once here, it is not obvious from the piece of the code what exactly you want, but please note that an exception object and exception handling mechanism are thread-local. Even if the catch clause is run in multiple threads, it will never be working with the same exception unless both a reference to the same exception object was passed between threads and copy was not made while rethrowing.
It is implementation-defined whether std::current_exception and std::rethrow_exception make a copy, and you should just consider protection from simultaneous writing if do writing for the case they don’t copy, if don’t want to make you code be a mishmash checking whether it was copied or not and handling the case if not (though it is possible, there is no any sensible reason for that).
It is safe to call std::current_exception() anywhere within the scope of the catch block, even inside of nested function calls. But once the catch block exits, its exception object is no longer valid, unless captured by std::current_exception().
I am running into an issue here because the return of stack.front() isn't pointing to anything when the stack is empty. So despite catching the exception, I end up getting bad access run-time errors.
Is there a better way to go about doing this? I want the program to continue functioning, even when certain functions are called and have errors.
You're running into issues because you immediately catch exception after throwing it. The exception doesn't get out of top() and you're calling getFront() on an empty stack. Rethrow your exception in the catch block or don't catch it all.
The following code terminates abnormally as no object is explicitly thrown. What is thrown by throw statement in the following code?
int main()
{
try{
cout<<"try";
throw ;
}
catch(...){
cout<<"catch";
}
return 0;
}
throw without an argument should only be used inside a catch statement, to rethrow the caught exception object. You code tries to use it outside the catch statement - instead you should pick a type to throw, if in doubt it's not unreasonable to start with std::runtime_error. For more options, see here. You can also throw your own types, but it's usually a good idea to derive them from one of the Standard-library provided types so client code has a better chance at specifying appropriate handling for all logically similar errors, rather than having to catch and handle them separately and being constantly updated for each new possible error.
FWIW, the Standard says in 15.1/9:
If no exception is presently being handled, executing a throw-expression with no operand calls std::terminate().
So very explicitly, the answer to "What is thrown..." is that no throwing is done, and std::terminate is called instead.
So the question is: "What happens when I throw outside a catch block?" The answer to this can be found in its documentation:
Rethrows the currently handled exception. Abandons the execution of the current catch block and passes control to the next matching exception handler (but not to another catch clause after the same try block: its compound-statement is considered to have been 'exited'), reusing the existing exception object: no new objects are made. This form is only allowed when an exception is presently being handled (it calls std::terminate if used otherwise). The catch clause associated with a function-try-block must exit via rethrowing if used on a constructor.
Emphasize mine.
In wikipedia we read:
Resource Acquisition Is Initialization RAII is a programming idiom
used in several object-oriented languages like C++, D, Ada and Vala.
The technique was invented by Bjarne Stroustrup to deal with resource
allocation and deallocation in C++. In this language, the only code
that can be guaranteed to be executed after an exception is thrown are
the destructors of objects residing on the stack.
I don't want to be over pedantic, whatever, but I really am not sure how to interpret this. Is this a slip of the tongue or is this correct? Aren't catch handlers guaranteed to be executed at least?
I know about RAII and what it is, I am focused here on this only code that can be guaranteed to be executed (..) are destructors of objects residing on the stack.
Strictly speaking, the quote is already wrong. When an exception is thrown and there's no matching handler for it, terminate can be called without unwinding the stack and calling any destructors. So, the statement that says that "destructors are guaranteed to be executed when an exception is thrown" is wrong.
As for catch handlers themselves, of course, it is only possible to execute a catch handler if the matching catch handler actually exists.
On top of that, even if the handler exists, there are other reasons that can throw a spanner in the works and prematurely terminate the processing of the exception before it reaches the catch handler. For example, it happens when an "unexpected" exception is thrown. If your function exception specification prohibits some specific exception type and an exception of such "prohibited" type attempts to "fly out" of that function, unexpected will be called immediately, instead of transferring control to the handler.
As mentioned in the comments, another typical situation is when new exception is thrown during stack unwinding triggered by a previous exception. This will result in terminate being called.
The only reason why I would say that Wikipedia is correct there is because if the exception causes the entire application to crash and stop execution, then it wouldn't make it down to the "catch" handler. For the most part you can guarantee that the catch clause will be found and executed.
Source: http://msdn.microsoft.com/en-us/library/fk6t46tz.aspx
I read code in a large project, that includs a lot of code like:
try
{
}
catch(...)
{
}
Literally, in the parenthesis after "catch", there is "..." in it. Not something like "exception e".
This makes me a little worry.
Is this practice good or safe?
thanks.
No, this is a terrible practice.
If you catch(...), you have no idea what you've caught. It catches all C++ exceptions (and on some platforms with some settings, it catches other exceptions too, like structured exceptions in Visual C++).
If you have no idea what exception was thrown, you have no idea what the state of the system is: how do you know whether it is safe for the program to continue running?
The only two ways that it is absolutely safe to exit a catch(...) block is to terminate the program or to rethrow the exception (using throw;). The latter is occasionally useful if you need to perform some cleanup when an exception is thrown but can't rely on a destructor.
catch(...) catches all exceptions.
Normally, you would not want to do this. You have no idea what it is you just caught, and if you leave the catch block you have just silently ignored some kind of error. This could lead to very bad things happening later on. Since you have no idea what error just happened, you have no way to recover from it, and thus the only reasonable thing to do is to either allow the exception to continue (re-throw it) or abort the program's execution (call abort() or exit()).
However, if you have some cleanup you need to perform, it may be reasonable to catch all exceptions, perform the cleanup, then re-throw the exception:
try {
// ...
} catch (...) {
abortTransaction();
throw;
}
That said, it's usually better to use so-called RAII classes to automate this cleanup:
DBTransaction txn = db.StartTransaction();
// do stuff that may throw; if it throws, txn will be destroyed,
// and its destructor can abort the transaction
// As such, an explicit try { } catch(...) { } isn't needed
It catches all exceptions. See this code:
try {
throw CSomeOtherException();
}
catch(...) { // Handle all exceptions
// Respond (perhaps only partially) to exception
throw; // Pass exception to some other handler
}
From MSDN
You do not need to declare this parameter; in many cases it may be
sufficient to notify the handler that a particular type of exception
has occurred. However, if you do not declare an exception object in
the exception-declaration, you will not have access to that object in
the catch handler clause.
A throw-expression with no operand re-throws the exception currently
being handled. Such an expression should appear only in a catch
handler or in a function called from within a catch handler. The
re-thrown exception object is the original exception object (not a
copy). For example:
Hope this helps!
This practice is safe only if you have proper handlers written for exceptions. Avoiding it is better in my opinion.