Topic: Exception while throwing an exception?
Author: "Ed Brey" <brey@afd.mke.etn.com>
Date: 1999/09/09 Raw View
Andy Larson <AndyLarson@prodigy.net> wrote in message
news:37D5AF88.8681E2AE@prodigy.net...
>
> Siemel B. Naran wrote:
> [...]
> > The default behaviour of std::terminate() is to call std::abort().
> > You can change the default behaviour at your option by using the
> > function std::set_terminate(void (*)()).
> >
> > Coding guideline: try to make your exception objects not throw.
> > To avoid risking to throw an out-of-memory or std::bad_alloc,
> > avoid dynamic memory in the exception object.
>
> I agree with your guidelines. I asked the question in the first place
> as the result a review of the standard exception classes in <stdexcept>,
> such as invalid_argument. The constructors for these classes don't
> contain an exception specification so it is implementation dependant
> whether or not they actually might throw an exception themselves. A
> corollary to this guideline would, therefore, seem to be "don't use the
> standard exceptions". Hmmmm.
Using a standard exception class, such as std::logic_error, as the argument
to throw is no worse than using any other standard library function
normally. It is just as implementation defined for std::vector as it is for
std::logic_error as to whether it throws some exception you weren't
expecting.
In the case of std::logic_error throwing an error in the constructor, it may
happen that the exception gets raised during the evaluation of the argument
to throw (and so the throw statement never finishes being executed), but
your catching code won't really care if the exception occurred a long time
before some throw statement or just a moment before a throw statement gets
executed. For example,
void fn()
{
std::vector<int> v;
fill_me_in(v);
std::cout "The first element is " << v.at(1) << endl;
}
When a function calling fn() from a try block catches the exception, it
won't care whether memory ran out (or whatever exception) while creating v,
filling in v, or when at() tries to raise the std::out_of_range (assuming
out_of_range's constructor might throw) if fill_me_in didn't do anything.
With so many places where constructors could throw bad_alloc or other
exceptions, why make the std::exception derivatives a special case?
Since the std::exception derivatives only specify a constructor and leave
the destructor to be compiler generated, and since the base class's
destructor (std::exception) has an empty throw specification, they will not
throw when destroyed. The same goes for copy construction. Therefore, they
will never cause terminate() to be called. I'm assuming here that an
implementation is not allowed to write a copy constructor or destructor
because those functions are not listed in 19.1.x. Please correct me if I'm
wrong about this.
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Biju Thomas <b_thomas@ibm.net>
Date: 1999/09/07 Raw View
Siemel B. Naran wrote:
>
> On 6 Sep 1999 20:53:57 GMT, Andy Larson <AndyLarson@prodigy.net> wrote:
>
> >What is the required behavior when the constructor of an exception
> >object throws an exception? For example, if an exception is thrown as
> >in
>
> The required behaviour is a call to std::terminate().
I can't find such a specification in the standard. Can you tell where
you found it?
> Coding guideline: try to make your exception objects not throw.
> To avoid risking to throw an out-of-memory or std::bad_alloc,
> avoid dynamic memory in the exception object.
>
> Coding guideline: try to make your destructors of exception as
> well as non-exception objects not throw. If an object is being
> destroyed because of an exception already in progress, then if
> the destructor throws, we have two exceptions. The result is a
> call to std::terminate().
Agreed with the guidelines. But, the standard specifying so is a bit
extreme.
--
Biju Thomas
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: postmast.root.admi.gov@iname.com (blargg)
Date: 1999/09/07 Raw View
In article <37D56411.F9600F29@ibm.net>, b_thomas@ibm.net wrote:
> Siemel B. Naran wrote:
> >
> > On 6 Sep 1999 20:53:57 GMT, Andy Larson <AndyLarson@prodigy.net> wrote:
> >
> > >What is the required behavior when the constructor of an exception
> > >object throws an exception? For example, if an exception is thrown as
> > >in
> >
> > The required behaviour is a call to std::terminate().
>
> I can't find such a specification in the standard. Can you tell where
> you found it?
In the section describing std::terminate() (15.5.1)
> > Coding guideline: try to make your exception objects not throw.
> > To avoid risking to throw an out-of-memory or std::bad_alloc,
> > avoid dynamic memory in the exception object.
> >
> > Coding guideline: try to make your destructors of exception as
> > well as non-exception objects not throw. If an object is being
> > destroyed because of an exception already in progress, then if
> > the destructor throws, we have two exceptions. The result is a
> > call to std::terminate().
>
> Agreed with the guidelines. But, the standard specifying so is a bit
> extreme.
What do you think should be specified instead?
As it says in the introduction for std::terminate,
"In the following situations exception handling must be abandoned for less
subtle error handling techniques."
Bjarne also discusses this reasoning in C++PL 2nd on page 322, C++PL 3rd
page 373 (specifically addressing exceptions in destructors), and on page
383 (essentially the same discussion mentioned above as in C++PL 2nd)
If you want something different to happen in this case, you are certainly
free to handle it differently yourself (within the constraints of the
language). I see exceptions as being, at the core, a non-local goto
(without any type information). The type information is an extra benefit
that can be handled explicitly in some other fashion by the programmer.
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andy Larson <AndyLarson@prodigy.net>
Date: 1999/09/08 Raw View
Darin Adler wrote:
>
> Andy Larson <AndyLarson@prodigy.net> wrote:
>
> > What is the required behavior when the constructor of an exception
> > object throws an exception? For example, if an exception is thrown as
> > in
> >
> > throw some_object(some_arguments);
> >
> > A constructor of some_object will be called. That constructor may, in
> > turn, throw an exception. Is the result of this that the original
> > exception, some_object, is not thrown and is replaced by the exception
> > that the some_object constructor threw?
>
> Yes.
>
> > I've searched through the IS to try and find the answer to this question
> > and have not found anything. Maybe someone here can help.
>
> Although the standard doesn't call this out as a special case, it's clear
> that the expression is evaluated just as any other expression, so throwing
> an exception would work as normal. There's no special state just because
> it's the argument to throw.
>
> -- Darin
Thanks Darin. This makes sense to me. It isn't obvious that attempting
to throw an exception of one type would result in an exception of a
different type actually being thrown, but this is really a pathological
case. I've heard of stranger results.
Andy
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Paul D. DeRocco" <pderocco@ix.netcom.com>
Date: 1999/09/08 Raw View
"Siemel B. Naran" wrote:
>
> On 6 Sep 1999 20:53:57 GMT, Andy Larson <AndyLarson@prodigy.net> wrote:
>
> >What is the required behavior when the constructor of an exception
> >object throws an exception? For example, if an exception is thrown as
> >in
>
> The required behaviour is a call to std::terminate().
I disagree. 15.5.1 only says that terminate() will be called if a second
exception is thrown once an exception has been thrown, which hasn't yet
happened if the constructor of an object to be thrown generates its own
exception.
--
Ciao, Paul D. DeRocco
Paul mailto:pderocco@ix.netcom.com
---
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andy Larson <AndyLarson@prodigy.net>
Date: 1999/09/08 Raw View
Siemel B. Naran wrote:
>
> On 6 Sep 1999 20:53:57 GMT, Andy Larson <AndyLarson@prodigy.net> wrote:
>
> >What is the required behavior when the constructor of an exception
> >object throws an exception? For example, if an exception is thrown as
> >in
>
> The required behaviour is a call to std::terminate().
I still can't find any such reference. Section 15.5.1 doesn't seem to
cover this case. Could you provide one?
> The default behaviour of std::terminate() is to call std::abort().
> You can change the default behaviour at your option by using the
> function std::set_terminate(void (*)()).
>
> Coding guideline: try to make your exception objects not throw.
> To avoid risking to throw an out-of-memory or std::bad_alloc,
> avoid dynamic memory in the exception object.
I agree with your guidelines. I asked the question in the first place
as the result a review of the standard exception classes in <stdexcept>,
such as invalid_argument. The constructors for these classes don't
contain an exception specification so it is implementation dependant
whether or not they actually might throw an exception themselves. A
corollary to this guideline would, therefore, seem to be "don't use the
standard exceptions". Hmmmm.
> Coding guideline: try to make your destructors of exception as
> well as non-exception objects not throw. If an object is being
> destroyed because of an exception already in progress, then if
> the destructor throws, we have two exceptions. The result is a
> call to std::terminate().
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Biju Thomas <b_thomas@ibm.net>
Date: 1999/09/08 Raw View
blargg wrote:
>
> In article <37D56411.F9600F29@ibm.net>, b_thomas@ibm.net wrote:
>
> > Siemel B. Naran wrote:
> > >
> > > On 6 Sep 1999 20:53:57 GMT, Andy Larson <AndyLarson@prodigy.net> wrote:
> > >
> > > >What is the required behavior when the constructor of an exception
> > > >object throws an exception? For example, if an exception is thrown as
> > > >in
> > >
> > > The required behaviour is a call to std::terminate().
> >
> > I can't find such a specification in the standard. Can you tell where
> > you found it?
>
> In the section describing std::terminate() (15.5.1)
I re-read it again. I still don't understand how this paragraph handles
the case mentioned by Andy.
For information, here is the relevant part that I could find:
<quote>
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,
[... other cases ...]
In such cases, termiate() is called.
</quote>
Does the constructor for the exception object fall under the above rule?
I don't think so. OTOH, if a copy constructor of the exception object
that the exception handling mechanism invokes internally throws, that
falls under the above criteria, and, should call terminate().
May be I should learn how to read standards better :-)
> What do you think should be specified instead?
IMHO, it should handle the second exception that is thrown by the
constructor.
Consider this case - the constructor for an exception object throws
std::bad_alloc. I think it is more prudent to propagate std::bad_alloc
than calling terminate().
--
Biju Thomas
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/09/08 Raw View
On 7 Sep 1999 19:53:57 GMT, Biju Thomas <b_thomas@ibm.net> wrote:
>Siemel B. Naran wrote:
>> On 6 Sep 1999 20:53:57 GMT, Andy Larson <AndyLarson@prodigy.net> wrote:
>>>What is the required behavior when the constructor of an exception
>>>object throws an exception? For example, if an exception is thrown as
>> The required behaviour is a call to std::terminate().
>
>I can't find such a specification in the standard. Can you tell where
>you found it?
I went by logic, because I don't know where in the standard to look for
the answer, and I should have said this. Here is my reasoning: the
"throw E()" begins a throw process. As E::E() throws an exception, we
have two exceptions in the picture. So the result is a call to
std::terminate.
But after reading the other replies, as well as a private email from a
concerned C++ citizen, I think that my reasoning is wrong. Consider
the following:
{ E e; throw e; } // version 1
It is obviously equivalent to
{ throw E(); } // version 2
Now in version 1, if E::E() throws an exception, say an exception of
type T, then it is this T exception-object that leaves the block.
As version 2 is equivalent to version 1, it is the exception of E::E()
or T that leaves the block.
The throw process only begins after the system has created the E
object, as another replier said.
--
--------------
siemel b naran
--------------
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Andy Larson <AndyLarson@prodigy.net>
Date: 1999/09/06 Raw View
What is the required behavior when the constructor of an exception
object throws an exception? For example, if an exception is thrown as
in
throw some_object(some_arguments);
A constructor of some_object will be called. That constructor may, in
turn, throw an exception. Is the result of this that the original
exception, some_object, is not thrown and is replaced by the exception
that the some_object constructor threw?
I've searched through the IS to try and find the answer to this question
and have not found anything. Maybe someone here can help.
Andy Larson
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Scott Robert Ladd" <scott@coyotegulch.com>
Date: 1999/09/07 Raw View
Andy Larson <AndyLarson@prodigy.net>...
> What is the required behavior when the constructor of an exception
> object throws an exception?
I can't find the reference to this in the Standard either, but as I
understand it, processing of an exception is halted when a new exception is
thrown. I just tried this example bit of code:
class XA
{
public:
// just an empty object
};
class XB
{
public:
XB()
{
throw XA();
}
};
void testConstructorEx()
{
try
{
throw XB();
}
catch (XB)
{
cout << "caught XB" << endl;
}
catch (XA)
{
cout << "caught XA" << endl;
}
catch (...)
{
cout << "caught WHAT?!?!?" << endl;
}
}
The result was "caught XA" in both Visual C++ 6.0 SP3 (windows) and gcc
2.95.1 (linux). I think that is the correct behavior, since only one
exception can be "in progress" at any given time.
--
* Scott Robert Ladd
* Coyote Gulch Productions - http://www.coyotegulch.com
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: sbnaran@uiuc.edu (Siemel B. Naran)
Date: 1999/09/07 Raw View
On 6 Sep 1999 20:53:57 GMT, Andy Larson <AndyLarson@prodigy.net> wrote:
>What is the required behavior when the constructor of an exception
>object throws an exception? For example, if an exception is thrown as
>in
The required behaviour is a call to std::terminate().
The default behaviour of std::terminate() is to call std::abort().
You can change the default behaviour at your option by using the
function std::set_terminate(void (*)()).
Coding guideline: try to make your exception objects not throw.
To avoid risking to throw an out-of-memory or std::bad_alloc,
avoid dynamic memory in the exception object.
Coding guideline: try to make your destructors of exception as
well as non-exception objects not throw. If an object is being
destroyed because of an exception already in progress, then if
the destructor throws, we have two exceptions. The result is a
call to std::terminate().
--
--------------
siemel b naran
--------------
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: "Darin Adler" <darin@bentspoon.com>
Date: 1999/09/07 Raw View
Andy Larson <AndyLarson@prodigy.net> wrote:
> What is the required behavior when the constructor of an exception
> object throws an exception? For example, if an exception is thrown as
> in
>
> throw some_object(some_arguments);
>
> A constructor of some_object will be called. That constructor may, in
> turn, throw an exception. Is the result of this that the original
> exception, some_object, is not thrown and is replaced by the exception
> that the some_object constructor threw?
Yes.
> I've searched through the IS to try and find the answer to this question
> and have not found anything. Maybe someone here can help.
Although the standard doesn't call this out as a special case, it's clear
that the expression is evaluated just as any other expression, so throwing
an exception would work as normal. There's no special state just because
it's the argument to throw.
-- Darin
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]
Author: Christopher Eltschka <celtschk@physik.tu-muenchen.de>
Date: 1999/09/07 Raw View
Andy Larson wrote:
>
> What is the required behavior when the constructor of an exception
> object throws an exception? For example, if an exception is thrown as
> in
>
> throw some_object(some_arguments);
>
> A constructor of some_object will be called. That constructor may, in
> turn, throw an exception. Is the result of this that the original
> exception, some_object, is not thrown and is replaced by the exception
> that the some_object constructor threw?
>
> I've searched through the IS to try and find the answer to this question
> and have not found anything. Maybe someone here can help.
Well, AFAIK the object is first constructed, then thrown.
If the constructor of the object throws, the object is not
constructed, and not thrown; instead the exception thrown
by the constructor of some_object, which _is_ thrown,
should propagate down.
I don't know how the copy constructor is handled: Is copying
the object seen as occuring before throw (i.e. the new exception
would be thrown instead of the (not) copied object), or is it
seen as part of the throw (i.e. resulting in a double exception
and therefore in a terminate call)?
[ comp.std.c++ is moderated. To submit articles, try just posting with ]
[ your news-reader. If that fails, use mailto:std-c++@ncar.ucar.edu ]
[ --- Please see the FAQ before posting. --- ]
[ FAQ: http://reality.sgi.com/austern_mti/std-c++/faq.html ]