views:

57

answers:

1

Hello, we have a funny problem with try catch and std::runtime_error. Can someone explain to me why this is returning "Unknown error" as output ? Thanks very much for helping me !

#include "stdafx.h"
#include <iostream>
#include <stdexcept>

int magicCode()
{
    throw std::runtime_error("FunnyError");
}

int funnyCatch()
{
    try{
        magicCode();
    } catch (std::exception& e) {
        throw e;
    }

}

int _tmain(int argc, _TCHAR* argv[])
{
    try
    {
        funnyCatch();
    }
    catch (std::exception& e)
    {
        std::cout << e.what();
    }
 return 0;
}
+12  A: 

The problem is with this line. Because throw with an expression uses the static type of that expression to determine the exception thrown, this slices the exception object constructing a new std::exception object copying only the base object part of the std::runtime_error that e is a reference to.

throw e;

To re-throw the caught exception you should always use throw without an expression.

throw;
Charles Bailey
18 seconds faster ... how does he do it ?!
Space_C0wb0y
Ah, `exception`'s copy constructor doesn't have to preserve `what()`. I didn't realise that.
Doug
Charles, I thought that throw e; would call the copy constructor std::exception(const std::exception e), which would create a correct copy of the exception ? Is it not the case ?
BlueTrin
Yes, it uses `std::exception`'s copy constructor. No, this won't necessarily result in a 'correct' copy of the exception as `std::exception` is only the base class of the exception that `e` actually refers to.
Charles Bailey
Thank you for the complete answer, I have been taught to always rethrow using throw, while investigating an issue, I was curious about why the message returned by what() was not preserved. Thanks to you I know the reason, Charles !
BlueTrin
Up until the draft from March this year, the standard says that the effect of calling `what()` on a copied exception is implementation-defined. As of March (N3090), the `exception` copy constructor must ensure that `strcmp(this->what(), rhs.what()) == 0` after copying an `rhs` with *dynamic* type of `exception`. So it's guaranteed to print "FunnyError" in C++0x as written.
Doug
Exception object slicing is also covered in *More Effective C++*, item 13.
Cubbi