29

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?

Rakete1111
  • 47,013
  • 16
  • 123
  • 162
dev-masih
  • 4,188
  • 3
  • 33
  • 55
  • 1
    See: http://stackoverflow.com/questions/1481612/what-is-the-difference-between-throw-and-throw-with-arg-of-caught-exception, http://stackoverflow.com/questions/1833982/in-c-is-there-a-difference-between-throw-and-throw-ex – Cody Gray - on strike Dec 07 '16 at 18:38

3 Answers3

41

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).

Community
  • 1
  • 1
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • with all respect to @StoryTeller answer, i accept yours because of extra link and your point at the end. – dev-masih Dec 07 '16 at 14:54
  • 3
    Nitpick, but I assume you mean `throw;`, as (AFAIK) `throw` on its own isn't valid. – Nic Dec 08 '16 at 05:48
32

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.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
7

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
  ^^^^^^
}
Community
  • 1
  • 1
Marco A.
  • 43,032
  • 26
  • 132
  • 246