Why to have default exception catch if default functionality is to rethrow? - c++

In function g(), commenting line LABEL(default handler) results in same output as with it. Why do we have default catch?
#include <iostream>
#include <exception>
using namespace std;
void h() {
//throw 1; //A
//throw 2.5; //B
throw 'a'; //C
//throw "add"; //D
}
void g() {
try {
h();
}
catch (int) { cout << "int"; }
catch (double) { cout << "double"; }
catch (...) { throw; } //LABEL - commenting this line gives same result
}
void f() {
try {
g();
}
catch (char) { cout << "Char"; }
catch (...) { throw; }
}
int main() { //main func
try {
f();
}
catch (...) { cout << "Unknown"; }
return 0;
}
Why is default catch needed?

To me question is unclear and could be interpreted in two ways:
Why does a default catch-mechanism exist at all: the other answers give meaningful answers).
Why does g have a default catch with throw;, and I see two possibilities: it documents that other exceptions have been considered, and it is easier to debug that case (by putting a breakpoint on it).

The default catcher exists to catch every exception that are not explicitly handled.
They are cases where you can be sure of which exceptions could be thrown, and default catcher is a little paranoid.
But let's say you want to catch one exception type to do something specific and you want to execute the same handler for all the other cases, the default handler prevent duplicates !

What you're doing here is you catch an exception which was not caught by the previous catch statements but you're throwing it further so that it can be caught elsewhere. It works the same as if the catch(...) statement wasn't there because if it is not, the exception not being caught by the proper catch goes higher to another try blocks (from g() to f() to main()) until it gets handled (in your case it is handled in main). If there is no catch to handle the exception then the system takes it over.
Note that throwing an exception in catch(...) is NOT default behavior. It is something you implemented in your code by adding throw. If you did e.g. cout << "..." then it would work differently comparing to not having catch(...), in which case the exception would be handled by f() and then by main()

Related

Detecting whether or not a catch block is being executed

I have an error logging function that's used through existing code. If possible, I would like to improve it by detecting when it's called from a catch block to extract additional information from the exception when it's available. During a catch block you can rethrow the exception and catch it locally.
void log_error()
{
try {
throw; // Will rethrow the exception currently being caught
}
catch (const std::exception & err) {
// The exception's message can be obtained
err.what();
}
}
If you aren't in the context of a catch block, this function will call std::terminate. I'm searching for a way of detecting rather or not an exception exists to be rethrown, is it safe to call throw;? I've found std::uncaught_exception but it seems to only apply to functions being executed as part of throwing an exception and is useless within the catch block. I've read through http://en.cppreference.com/w/cpp/error but I can't seem to find any applicable mechanism.
#include <stdexcept>
#include <iostream>
struct foo {
// prints "dtor : 1"
~foo() { std::cout << "dtor : " << std::uncaught_exception() << std::endl; }
};
int main()
{
try
{
foo bar;
throw std::runtime_error("error");
}
catch (const std::runtime_error&)
{
// prints "catch : 0", I need a mechanism that would print 1
std::cout << "catch : " << std::uncaught_exception() << std::endl;
}
return 0;
}
Workarounds I've found include simply implementing a different function to be called from catch blocks but this solution wouldn't be retroactive. Another would be to use a thread_local flag with custom exception classes to know when the current thread has constructed an exception but not destroyed it, but this seems error prone and would be incompatible with standard and existing exception classes. Example for this weak workaround :
#include <exception>
struct my_base_except : public std::exception
{
my_base_except() { ++error_count; }
virtual ~my_base_except() { --error_count; }
my_base_except(const my_base_except &) { ++error_count; }
my_base_except(my_base_except&&) { ++error_count; }
static bool is_in_catch() {
return error_count > 0;
}
private:
static thread_local int error_count;
};
thread_local int my_base_except::error_count = 0;
void log_error()
{
if (my_base_except::is_in_catch())
{
// Proceed to rethrow and use the additional information
}
else
{
// Proceed with the existing implementation
}
}
Does a standard feature exists to solve this problem? If not, is there a more robust work-around than the ones I've identified here?
std::current_exception might be what you are looking for.
std::current_exception returns an std::exception_ptr, which is a pointer type to the current handled exception, or nullptr if no exception is being handled. The exception can be rethrown with std::rethrow_exception.

Identify C++ exception thrown in terminate

Is there a way to identify what type of exception was thrown in the terminate handler I set with set_terminate?
I would like for programs in my suite to pop up a message box if one of my exceptions is thrown, but not if the exception came from elsewhere.
Edit: code tried based on Brian's answer below. It doesn't do any of the cout's after the throw;
// set_terminate example
#include <iostream> // std::cerr
#include <exception> // std::set_terminate
#include <cstdlib> // std::abort
using namespace std;
class FooException {};
class BarException {};
void my_terminate() {
try {
cout << "This line gets printed... those below do not.\n";
throw; // rethrows
}
catch (FooException) {
cout << "FooException.\n";
// pop up message box
}
catch (BarException) {
cout << "BarException.\n";
// pop up message box
}
catch (...) {
cout << "Unclassified exception.\n";
// not one of my exceptions
abort();
}
cout << "Doesn't print this either.\n";
}
int main (void)
{
std::set_terminate (my_terminate);
throw FooException ();
return 0;
}
This may be a Visual Studio problem. (It won't call dtors either on its way out.) I'm going to ask another question about getting Visual to go to the right places, and then try addressing this question again.
An exception is still considered "active" inside the terminate handler (see C++11 §15.3/7 and §15.3/8). Therefore it can be rethrown or accessed with current_exception.
void my_terminate() {
try {
throw; // rethrows
} catch (FooException) {
// pop up message box
} catch (BarException) {
// pop up message box
} catch (...) {
// not one of my exceptions
abort();
}
}
You could create your own exception-base-class, catch all exceptions in main and re-throw all exceptions derived from your base-class. this way, only your exceptions will terminate the Programm with terminate
The best solution is to derive all exception classes from std::exception
Then you can do
try
{
}
catch . . .
catch . . .
catch . . .
catch (std::exception &ee)
{
cerr << ee.what () << end ;
}
and be sure to catch everything.

Why C++ biased towards destructor's exception?

#include <iostream>
using namespace std;
class Cls
{
public:
~Cls()
{
throw "exp";
}
};
int main()
{
try
{
Cls c;
throw "exp";
}
catch (...)
{
cout << "Why this doesn't call" << endl;
}
}
When I execute this code, it doesn't goes in catch block. And give following exception,
But, when I run this code with little modification, it goes to catch block.
int main()
{
try
{
throw "exp";
throw "exp";
}
catch (...)
{
cout << "Why this doesn't call" << endl;
}
}
Output:
Both the above code throws 2 exception, then why Compiler is biased in destructor's case?
In the first case you first throw from the try block and then the stack unwinding throws from Cls's destructor. So you have two exceptions to be handled. C++ handles this situation by calling terminate.
Because of the peculiarity of throwing from destructors, C++11 defines that all destructors are noexcept by default. Then even if there is no other exception to be handled, the exception from a destructor will cause terminate to be called.
The second case is OK because as soon as you throw the first exception try block is left and the exception is handled in the catch block.

why does it cause termination if I try to throw something inside a catch block in C++

I have the following C++ code and it gives me a surprise.
The problem is that if I throw something except re-throw inside the catch block,
the program will be terminated by calling abort and give the error message in GCC4,
"terminate called after throwing an instance of 'int'".
If I just use "throw;" to re-throw inside the catch block, everything will be fine.
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
int main()
{
try{
throw std::string("first throw");
}
catch(std::string &x){
try{
std::cout << x << std::endl;
// throw; // if I use this line, all is fine.
throw int(2); // but if I use this line, it causes Abort() to be called
}
catch (int &k){
throw;
}
catch(...)
{
cout << "all handled here!"<< endl;
}
}
catch(...){
std::cout<< "never printed" << endl;
}
}
If you throw an int, then it won't be handled; it will be caught by the inner catch (int &k) handler, which rethrows it; and there is no outer handler to catch the rethrown exception, since you're already in an outer catch block. So in this case, terminate is called due to an unhandled exception.
If you rethrow the string, then it's caught by the inner catch(...) handler; this doesn't rethrow, so the exception has then been handled.
You throw is not inside any try handler thus it leads to abort being called.
Here is your code with the indentation cleaned up a bit and some comments inline:
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;
int main()
{
try {
throw std::string("first throw");
}
catch (std::string &x) {
try {
std::cout << x << std::endl;
// throw; // if I use this line, all is fine.
throw int(2); // but if I use this line, it causes Abort() to be called
}
catch (int &k) {
// Catches and rethrows exception. Not inside a try thus leads to abort.
throw;
}
catch (...) {
// Will handle the case where the string is rethrown instead. No abort.
cout << "all handled here!"<< endl;
}
}
catch (...) {
std::cout<< "never printed" << endl;
}
}

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.