Topic: std::terminate -- is it a defect?


Author: restor <akrzemi1@gmail.com>
Date: Fri, 9 Oct 2009 19:31:39 CST
Raw View
Hi,
Could someone tell whether the following two things are bugs in the
standard, or just my failure to understand their meaning?

1.
18.8.3.3/2 (effects of std::terminate) says "Calls the
terminate_handler function in effect immediately after evaluating the
throw-expression (18.8.3.1), if called by the implementation, [...]".
What does "in effect immediately after evaluating the throw-
expression" add to the meaning? Does it mean that the following code
prints "IMMEDIATELY"?

 void immediately() {
   std::cout << "IMMEDIATELY" << std::endl;
 }

 void later() {
   std::cout << "LATER" << std::endl;
 }

 struct Exc {
   Exc() {}
   Exc( Exc const& ) {
         std::set_terminate( later );
       }
 };

 int main() {
   std::set_terminate( immediately );
       throw Exc(); // copy ctor calls set_terminate
 }

At the moment when the exception is copied into te special EH
memorythe terminate handler is function later(), but at the point
"immediately after evaluating the throw-expression", i.e. before the
copy constructor, the handler was immediately(), hence, the latter is
called. Is this interpretation correct?

2.
15.5.1/1 lists a number of situations, when std::terminate is called,
among others: "when construction of a non-local object with static or
thread storage duration exits using an exception".
What about a throw from a function whose return value is used to
initialize a global? i.e.:

 int val = iMayThrow();
 int main(){}

If iMayThrow() throws, it naturally qualifies for the call to
std::terminate. I.e. it is not any different from "construction of a
non-local object with static or thread storage duration", yet
"construction of a non-local object with static or thread storage
duration" doesn'tseem to cover that case.

Regards,
&rzej

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use
mailto:std-c++@netlab.cs.rpi.edu<std-c%2B%2B@netlab.cs.rpi.edu>
]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Florian Weimer <fw@deneb.enyo.de>
Date: Sun, 11 Oct 2009 17:02:20 CST
Raw View
* restor:

> Hi,
> Could someone tell whether the following two things are bugs in the
> standard, or just my failure to understand their meaning?
>
> 1.
> 18.8.3.3/2 (effects of std::terminate) says "Calls the
> terminate_handler function in effect immediately after evaluating the
> throw-expression (18.8.3.1), if called by the implementation, [...]".
> What does "in effect immediately after evaluating the throw-
> expression" add to the meaning? Does it mean that the following code
> prints "IMMEDIATELY"?

I think that is unspecified because the constructor call can be
eliminated.  I suppose the requirement express here is that
destructors should not be called prior to calling the
terminate_handler function (that is, the stack is not unwound).

> 2.
> 15.5.1/1 lists a number of situations, when std::terminate is called,
> among others: "when construction of a non-local object with static or
> thread storage duration exits using an exception".
> What about a throw from a function whose return value is used to
> initialize a global? i.e.:

This might be a defect.  It should probably read "initialization"
instead of "construction".

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: restor <akrzemi1@gmail.com>
Date: Mon, 12 Oct 2009 10:25:20 CST
Raw View
> > 18.8.3.3/2 (effects of std::terminate) says "Calls the
> > terminate_handler function in effect immediately after evaluating the
> > throw-expression (18.8.3.1), if called by the implementation, [...]".
> > What does "in effect immediately after evaluating the throw-
> > expression" add to the meaning? Does it mean that the following code
> > prints "IMMEDIATELY"?
>
> I think that is unspecified because the constructor call can be
> eliminated.  I suppose the requirement express here is that
> destructors should not be called prior to calling the
> terminate_handler function (that is, the stack is not unwound).

Thanks for this explanation. My interpretation was (perhaps my example
was unfortunate) that if for any reason the terminate_handler was
changed after the 'unfortunate' throw instruction, but before the
determination that terminate() must be called, we do not call the
current terminate_handler, but the one that was current "immediately
after evaluating the throw-expression." I claim that the standard has
a bug here because the sentence 18.8.3.3/2 is ambiguous: there are at
least two meaningful interpretations.

Regards,
&rzej




--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Johannes Schaub (litb)" <schaub-johannes@web.de>
Date: Mon, 12 Oct 2009 10:23:39 CST
Raw View
restor wrote:

> Hi,
> Could someone tell whether the following two things are bugs in the
> standard, or just my failure to understand their meaning?
>
> 1.
> 18.8.3.3/2 (effects of std::terminate) says "Calls the
> terminate_handler function in effect immediately after evaluating the
> throw-expression (18.8.3.1), if called by the implementation, [...]".
> What does "in effect immediately after evaluating the throw-
> expression" add to the meaning? Does it mean that the following code
> prints "IMMEDIATELY"?
>
>  void immediately() {
>    std::cout << "IMMEDIATELY" << std::endl;
>  }
>
>  void later() {
>    std::cout << "LATER" << std::endl;
>  }
>
>  struct Exc {
>    Exc() {}
>    Exc( Exc const& ) {
>          std::set_terminate( later );
>        }
>  };
>
>  int main() {
>    std::set_terminate( immediately );
>        throw Exc(); // copy ctor calls set_terminate
>  }
>
> At the moment when the exception is copied into te special EH
> memorythe terminate handler is function later(), but at the point
> "immediately after evaluating the throw-expression", i.e. before the
> copy constructor, the handler was immediately(), hence, the latter is
> called. Is this interpretation correct?
>

There are several expressions here:

assignment-expression
   -> throw-expression
     -> throw assignment-expression[opt]

The standard refers to the throw-expression, not to its operand. Evaluating
it initializes an exception-object from the temporary "Exc()". So if the
implementation doesn't elide out the copy, "later" is installed and "LATER"
will be printed. If the copy is elided out, "IMMEDIATELY" is printed.

I'm not sure whether or not the temporary object (meaning "Exc()") is
destroyed before or after calling terminate, though. Notice that it's not an
"automatic" object (the storage duration of temporaries are unspecified), so
it's not affected by "stack unwinding".

But i strongly feel that the destructor of it *should* be called according
to the wording: It's the last step in evaluating the full-expression where
it is contained (and the full-expression is the throw-expression here, if
i'm not mistaken). Since the implicit call is done immediately *after*
evaluating the throw-expression, this indicates that the temporary object
should be destroyed before the call.

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]