Eduard Rostomyan
Eduard Rostomyan

Reputation: 6546

Exception catching mechanism, C++

Consider this code:

int main()
{
    try 
    {
        throw std::range_error("");
    }
    catch (std::bad_alloc) 
    {
        std::cout << "AAAA" << std::endl;
        throw;
    }
    catch (std::range_error) 
    {
        std::cout << "BBB" << std::endl;
        throw;
    }
    catch (std::exception)
    {
        std::cout << "CCC" << std::endl;
    }
    std::cout << "DDD" << std::endl;
}

Here I throw an exception of type std::range_error and trying to catch it.
Logically the first catch block cannot catch it because of type mismatch(std::bad_alloc and std::range_error).
The second catch block must catch it because they are the same types of std::range_error.
And also, when I rethrow the exception in second catch block it must be caught in the third catch block.

So my output must be

BBB
CCC
DDD

But I only get the BBB output with the termination.

Can anybody please explain me the behavior??

Upvotes: 5

Views: 849

Answers (3)

WhiZTiM
WhiZTiM

Reputation: 21576

When you re-throw an exception, you are throwing it completely out of the context of the current exception handling block.... So,

try 
{
    throw std::range_error("");
}
catch (std::bad_alloc) 
{
    std::cout << "AAAA" << std::endl;
    throw;
}
catch (std::range_error) 
{
    std::cout << "BBB" << std::endl;
    throw;
}
catch (std::exception)
{
    std::cout << "CCC" << std::endl;
}

is one exception handling block. Therefore, on meeting the first throw in any of the catch blocks, it leaves the whole block to look for another handling block (try-catch) outside the current scope. if not found, the program terminates.

Please see try-catch block in C++

To print as you initially thought ... Live On Coliru ...

int main()
{
    try{
        try{
            try{
                throw std::range_error("");
            }
            catch (std::bad_alloc) {
                std::cout << "AAAA" << std::endl;
                throw;
            }
        }
        catch (std::range_error) {
            std::cout << "BBB" << std::endl;
            throw;
        }
    }
    catch (std::exception){
        std::cout << "CCC" << std::endl;
    }
    std::cout << "DDD" << std::endl;
}

Prints:

BBB
CCC
DDD

For the record: please avoid using exceptions for control flow that could be done with simple if-else ladder in production code

Upvotes: 6

robor
robor

Reputation: 3089

To re-catch the range_error and new outer try catch block is required.

#include <iostream>

int main()
{
  //outer try catch ------------------------
  try { 

    // inner try catch ---------------------
    try 
    {
      throw std::range_error("");
    }
    catch (std::bad_alloc) 
    {
      std::cout << "AAAA" << std::endl;
      throw;
    }
    catch (std::range_error) 
    {
      std::cout << "BBB" << std::endl;
      throw;
    }
    // -------------------------------
  }

  catch (std::exception)
  {
    std::cout << "CCC" << std::endl;
  }
  // --------------------------------

  std::cout << "DDD" << std::endl;
}

Output

BBB
CCC
DDD

Upvotes: 5

Barry
Barry

Reputation: 302708

This throw:

catch (std::range_error) 
{
    std::cout << "BBB" << std::endl;
    throw; // <== this one
}

isn't itself within the body of a try, so when the exception handling mechanism will keep going out one scope at a time until it finds one. Since there is no other outer try, the exception isn't caught at all.

There is no reentrance in exception handling.

Upvotes: 4

Related Questions