Error with catching std::runtime_error as std::exception

15,281

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;
Share:
15,281
BlueTrin
Author by

BlueTrin

Working in an investment bank, writing analytics for Fixed Income products in a combination of C++, C# and Python.

Updated on July 23, 2022

Comments

  • BlueTrin
    BlueTrin almost 2 years

    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;
    }
    
  • Björn Pollex
    Björn Pollex over 13 years
    18 seconds faster ... how does he do it ?!
  • Doug
    Doug over 13 years
    Ah, exception's copy constructor doesn't have to preserve what(). I didn't realise that.
  • BlueTrin
    BlueTrin over 13 years
    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 ?
  • CB Bailey
    CB Bailey over 13 years
    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.
  • BlueTrin
    BlueTrin over 13 years
    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 !
  • Doug
    Doug over 13 years
    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.
  • Cubbi
    Cubbi over 13 years
    Exception object slicing is also covered in More Effective C++, item 13.
  • BlueTrin
    BlueTrin over 9 years
    I didn't catch by value copy.