Hussen Baban Hussen Baban - 2 months ago 6
C++ Question

Why is there a need for a try block before catch in exception handling c++

Is it possible to throw an exception and catch it without using a try block ?
ex:

int main()
{
throw 1;
catch(int){
std::cerr << "caught exception\n";
}
return 0;
}

Answer

There is a slight difference in the behavior of program control flow during an exception in flight. try-catch blocks hopefully brings the program back to the usual control flow.

When an exception is thrown at any point in the program. Normal program control flow halts. The program control flow now goes through the runtime's mechanism for exception handling. This is different from what is normal. For the normal, destructors for automatic storage always runs when control flow reaches the end of scope (lifetime) "}". For exceptions in flight, they run earlier than normal

Consider this (note the comments);

MyClass foo(){
{
    MyClass c;
    c.call(balhhh); //assuming this throws

    // (1)

    ....
    return c;
 }

void bar(){
     std::map<K,V> mp;
     auto c = foo();

     // (2)

     mp.insert(c);
     ....
}

When you call bar, we can see how control flow is per-maturely leaves foo() at // (1), no other code after // (1) is executed within the scope of foo(), the same thing happens when foo() has been unwound, and we are now at // (2)

This happens throughout stack-unwinding process, And this recursively unwinds all functions... until we are back to main() where std::terminate is called.


Now, with a try-catch block, the compiler generates code that suspends that early exit behavior after program has moved to a catch block (in search for a matching handler), and if the exception is handled, control flow goes back to normal.

Consider:

MyClass foo() 
    try {
        MyClass c;
        c.call(balhhh); //assuming this throws

        // (1)

        ....
        return c;
     }
     catch(...){
          ...
     }

void bar(){
     std::map<K,V> mp;
     auto c = foo();

     // (2)

     mp.insert(c);
     ....
}

Now, when the exception leaves, control flow leaves the norm at // (1) to search for the handler in the associated catch, if the exception was handled, the program goes back to the normal control flow. Code after // (2) will execute now...


As you can see from the explanation, try-catch blocks are the only way as dictated by C++ standards, to restore normal program control flow after an exception is thrown.

int main()
{
    throw 1;   //fine, program control leaves the whole of main at this point.
    catch(int){    //illegal, like using an else block without an if
       std::cerr << "caught exception\n";
    }
    return 0;
}

Even if the above code was legal, throw means control will leave the whole of the enclosing scope at the throw site.

Comments