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

6.4k views Asked by At

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

There are 2 answers

0
Martin Liversage On

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;
    }
}
3
Mike Seymour On

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.