dev-masih
dev-masih

Reputation: 4756

ex.what() changes in nested try-catch

I have a nested try-catch code like below:

void A()
{
    try
    {
        //Code like A = string(NULL) that throws an exception
    }
    catch(std::exception& ex)
    {
        cout<<"in A : " << ex.what();
        throw ex;
    }
}

void B()
{
   try
   {
       A();
   }
   catch(std::exception& ex)
   {
       cout<<"in B : " << ex.what();
   }
}

After running this I got this result:

in A: basic_string::_M_construct null not valid
in B: std::exception

As you can see, ex.what() works OK in function A and tell me the correct description, but in B ex.what() tells me just std::exception. Why does this happen?

Am I throwing something different or wrong in the catch clause of function A? How do I throw a nested exception so that I can get the exact exception description in B?

Upvotes: 29

Views: 2675

Answers (3)

Bathsheba
Bathsheba

Reputation: 234785

Replace throw ex; with throw;.

Doing the latter will re-throw the exception ex, by reference, so obviating the hazards in attempting to make a value copy: see What is object slicing?

(Note that you are allowed to modify ex even if you write throw).

Upvotes: 41

Marco A.
Marco A.

Reputation: 43662

You're slicing the original exception object, try with

try {
  throw std::runtime_error("Hello world");
}
catch (std::exception& ex)
{
  cout << "in A : " << ex.what();
  throw; // Rethrows the original exception - no copy or slicing
  ^^^^^^
}

Upvotes: 7

You are throwing a copy of the exception ex in A. Which causes object slicing that turns the concrete exception into std::exception.

To rethrow the actual exception you caught polymorphically, use the throw; statement.

It's worth keeping in mind what Scott Meyers says in his book. You throw by value, and should catch by reference.

Upvotes: 32

Related Questions