Reputation: 4756
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
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
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
Reputation: 170153
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