The new expression in the try block throws a bad_allocexception in my computer.
Note that the catch clause receives an exception object by value, not by reference. How come e.what() prints "bad allocation" ? I thought it would be sliced.
#include <iostream>
int main()
{
try
{
int* p = new int[0x1F000000];
}
catch(std::exception e)
{
std::cout << e.what() << std::endl;
}
}
Visual Studio (Dinkumware?) uses an implementation of
std::exceptionthat contains internal storage† for the message. (Complete with a non-standard constructor that accepts a string.)Because of this, no virtual dispatch is actually needed to get the error message, it survives any slicing.
A more orthodox implementation would indeed print a generic exception message, because the derived object was sliced off. (Effectively, MS has made
std::exceptionandstd::runtime_errorequivalent. There’s nothing wrong with this, since the return value ofstd::exception::whatis implementation-defined, but it explains your results.)†Internal storage here is used loosely. It doesn’t have an internal buffer, but it has a
const char*and abool. Theconst char*points to the message (the return value ofwhat()), and theboolis a flag determining if the buffer should be deleted.It’s like this:
You see now that
bad_allocworks like this:Slicing doesn’t affect the message because the message “exists” in the base class.
Other compilers, like GCC and LLVM, implement it a bit more straight-forwardly:
Here, slicing would affect your outcome. (That said, after all this: always catch by reference.)