Re: An exception that throws while it is being thrown, no terminate?
On Dec 3, 6:17 pm, "Bo Persson" <b...@gmb.dk> wrote:
Niels Dekker - no reply address wrote:
class MyException: public std::logic_error
{
std::string m_string;
public:
MyException(const std::string& arg)
:
std::logic_error(arg), m_string(arg) {}
// A throwing copy-constructor!
MyException(const MyException& arg)
:
std::logic_error(arg), m_string(arg.m_string)
{
// Triggering std::terminate...?
throw std::bad_alloc();
}
~MyException() throw() { }
};
int main()
{
const MyException constException("what");
try
{
// Here the copy-constructor is called:
throw constException;
}
catch( std::bad_alloc & )
{
// Here is where we get!
return EXIT_FAILURE;
}
}
Shouldn't the above test program call std::terminate,
instead of catching the std::bad_alloc?
Martin replied:
AFAIK, the implementation is *allowed* to copy the
exception object but is not required to, so it may just be
that at runtime the copy-ctor is never called.
Thanks, Martin. In some cases, the compiler is indeed
allowed to omit the copy-constructor call. But in this case,
I don't think it is allowed. The test program certainly
*does* call the copy-constructor of MyException, when
compiled by VC. So don't you think it should trigger a call
to std::terminate?
Doesn't note 141 from the C++ Working Draft apply here? As
follows:
"For example, if the object being thrown is of a class with
a copy constructor, std::terminate() will be called if that
copy constructor exits with an exception during a throw."
See also: Working Draft, Standard for Programming Language C++,
section 15.5.1, The std::terminate() function, [except.terminate],
www.open-std.org/JTC1/sc22/WG21/docs/papers/2009/n3000.pdf
No, it doesn't really apply because the std::bad_alloc appears
before and not during the throw! :-)
You throw by value, and I believe the implementation is
allowed to create a copy *before* the copy is thrown. This is
similar to evaluating all parameters before calling a
function.
I don't see where you get this. There are two parts of a throw
expression: the expression which defines what is being thrown,
and the throw itself. In this case, the expression which
defines what is being thrown is simply constExpression, an
lvalue of type MyException. I don't see any place in the
standard that allows any copies here. Then we enter into the
throw itself, which does copy. But here, 15.5.1 is clear:
In the following situations exception handling must be
abandoned for less subtle error handling techniques:
-- when the exception handling mechanism, after completing
evaluation of the expression to be thrown but before the
exception is caught (15.1), calls a user function that
exits via an uncaught exception,
A user defined copy constructor is in fact about the only I can
think of which could be called, and it is, in fact, mentionned
in a footnote---non normative, but a very clear indication of
intent.
--
James Kanze