Topic: switch and lifetime of temporaries


Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 23 Mar 1995 21:30:50 GMT
Raw View
In article 95Mar21120154@king.trs.ntc.nokia.com, wikman@king.trs.ntc.nokia.com (Johan Wikman) writes:

>>>>>> "SC" == Steve Clamage <clamage@Eng.Sun.COM> writes:
>SC> The latest decision of the C++ Committee (last year sometime) is that
>SC> temporaries are destroyed at the end of the full-expression in which
>SC> they are created (unless bound to a reference).

>What does 'unless bound to a reference' mean here?

It means "unless a reference is initialized with the object". The object then
lives as long as the reference does.

> String foo();
>
> void bar()
> {
>     const String& s = foo();
>     ...
>     // Is s valid here ?

Yes. The temporary object that s refers to will be destroyed at function exit.
---
Steve Clamage, stephen.clamage@eng.sun.com






Author: jason@cygnus.com (Jason Merrill)
Date: 24 Mar 1995 01:00:44 GMT
Raw View
>>>>> Johan Wikman <wikman@king.trs.ntc.nokia.com> writes:

>>>>> "SC" == Steve Clamage <clamage@Eng.Sun.COM> writes:

SC> The latest decision of the C++ Committee (last year sometime) is that
SC> temporaries are destroyed at the end of the full-expression in which
SC> they are created (unless bound to a reference).

> What does 'unless bound to a reference' mean here?

This definition is still being refined, since it could be interpreted to
apply to

String foo ();

String & bar () { return foo (); }

or

struct A ()
{
  String & r;
  A(): r (foo ()) { }
};

in both cases, the temporary object is destroyed before the reference goes
out of scope.

> Will this work?

Yes; this is the usage that was intended.

>  String foo();

>  void bar()
>  {
>      const String& s = foo();
>      ...
>      // Is s valid here ?
>  }

Jason




Author: wikman@king.trs.ntc.nokia.com (Johan Wikman)
Date: 21 Mar 1995 10:01:54 GMT
Raw View
>>>>> "SC" == Steve Clamage <clamage@Eng.Sun.COM> writes:

SC> The latest decision of the C++ Committee (last year sometime) is that
SC> temporaries are destroyed at the end of the full-expression in which
SC> they are created (unless bound to a reference).

What does 'unless bound to a reference' mean here? Will this work?

 String foo();

 void bar()
 {
     const String& s = foo();

     ...

     // Is s valid here ?
 }

  Johan

--
--
johan.wikman@ntc.nokia.com; C=FI,A=Elisa,P=Nokia Telecom,S=Wikman,Gi=Johan
TL4E - P.P. Box 12, SF-02611 Espoo 61, Finland




Author: andycarlson@attmail.com (Andy Carlson)
Date: Tue, 14 Mar 1995 11:04:34 GMT
Raw View
Apologies if this issue has already been discussed, but I am not a
regular in this group.

I have recently been in touch with one of our compiler suppliers
regarding a problem we have building some bought in class library code.

The problem relates to construction/destruction of temporary objects
within a switch statement. It appears that in some circumstances, if
temporaries are created implicitly within one case (say case 1),
executing a different case (case 2) can result in destructor calls on
temporaries from case 1. As there is no corresponding constructor call,
this can cause code to break.

According to the supplier, this behaviour is in line with current
discussions on the ANSI standard relating to lifetime of temporaries.

Can anyone point me at some more detailed information stating exactly
what the proposed standard specifies on lifetime of temporaries?

Thanks
----------------------------------------------------------------------
Andy Carlson. AT&T ISTEL Ltd            Tel: +44 1527 494358
E-Mail: andycarlson@attmail.com         Fax: +44 1527 60141
                        after 20-March: Fax: +44 1527 494318





Author: jason@cygnus.com (Jason Merrill)
Date: 14 Mar 1995 23:10:45 GMT
Raw View
>>>>> Andy Carlson <andycarlson@attmail.com> writes:

> The problem relates to construction/destruction of temporary objects
> within a switch statement. It appears that in some circumstances, if
> temporaries are created implicitly within one case (say case 1),
> executing a different case (case 2) can result in destructor calls on
> temporaries from case 1. As there is no corresponding constructor call,
> this can cause code to break.

> According to the supplier, this behaviour is in line with current
> discussions on the ANSI standard relating to lifetime of temporaries.

Your supplier is deluded.  How can you destroy an object that was never
created?  It would make a mockery of any attempt to create a coherent
object model for C++.

In any case, I don't understand how a temporary object from one case could
live long enough to be destroyed after the code specifically for that case.
In

switch (i)
{
  case 1:
    j = A().get_int; break;
  case 2:
    j = 3; break;
}

the temporary created by A() is destroyed at the semicolon, so it does not
affect case 2.  I suspect that your supplier is still using the old cfront
lifetime-of-temporaries semantics, whereby (as I recall) temporaries would
live until end of scope.

The tricky cases involve ||, && and ?:, not switch.

> Can anyone point me at some more detailed information stating exactly
> what the proposed standard specifies on lifetime of temporaries?

    12.2  Temporary objects                            [class.temporary]

2   When  a compiler introduces a temporary object of a class that has a
    non-trivial constructor (_class.ctor_), it shall ensure that a  con-
    structor  is  called  for  the  temporary  object.   Similarly,  the
    destructor shall be  called  for  a  temporary  with  a  non-trivial
    destructor   (_class.dtor_).    Ordinarily,  temporary  objects  are
    destroyed  as  the  last  step  in  evaluating  the  full-expression
    (_intro.execution_)  that  (lexically) contains the point where they
    were created.  This is true even if that evaluation ends in throwing
    an exception.

Jason




Author: clamage@Eng.Sun.COM (Steve Clamage)
Date: 14 Mar 1995 23:40:47 GMT
Raw View
In article 1vo@demon.co.uk, andycarlson@attmail.com (Andy Carlson) writes:
>
>I have recently been in touch with one of our compiler suppliers
>regarding a problem we have building some bought in class library code.
>
>The problem relates to construction/destruction of temporary objects
>within a switch statement. It appears that in some circumstances, if
>temporaries are created implicitly within one case (say case 1),
>executing a different case (case 2) can result in destructor calls on
>temporaries from case 1. As there is no corresponding constructor call,
>this can cause code to break.

English descriptions of C++ code are hard to evaluate, but this
sounds like a compiler bug, not a language rule.

>According to the supplier, this behaviour is in line with current
>discussions on the ANSI standard relating to lifetime of temporaries.
>
>Can anyone point me at some more detailed information stating exactly
>what the proposed standard specifies on lifetime of temporaries?

The latest decision of the C++ Committee (last year sometime) is that
temporaries are destroyed at the end of the full-expression in which
they are created (unless bound to a reference). A "full-expression" is
an expression which is not part of any other expression. Not all compilers
implement this rule yet, and may follow the old rule. The old rule
allowed destroying the temp at any time up to the end of the block.

It should not be possible to write well-formed code in which a temporary
is destroyed which was not created. Either the compiler did not catch
an error in the code, or the compiler did not properly keep track of
its temporaries. (The compiler is not required to catch all errors in
code; some constructs have undefined behavior and allowing your program
to crash is one alternative open to the compiler.)

To be fair, keeping track of the temps is very difficult,
and most compilers have historically had bugs in that area.

---
Steve Clamage, stephen.clamage@eng.sun.com






Author: ball@Eng.Sun.COM (Mike Ball)
Date: 15 Mar 1995 00:06:20 GMT
Raw View
In article gn1@engnews2.Eng.Sun.COM, clamage@Eng.Sun.COM (Steve Clamage) writes:
> In article 1vo@demon.co.uk, andycarlson@attmail.com (Andy Carlson) writes:
> English descriptions of C++ code are hard to evaluate, but this
> sounds like a compiler bug, not a language rule.

Yes, but a reasonable statement for a compiler writer to make is "That would
never occur with the new rules on temporaries".  I wonder if perhaps Mr.
Carlson might have misunderstood such a statement as saying that it was
correct behavior under the old rules.

> >According to the supplier, this behaviour is in line with current
> >discussions on the ANSI standard relating to lifetime of temporaries.
> >
> >Can anyone point me at some more detailed information stating exactly
> >what the proposed standard specifies on lifetime of temporaries?
>
> The latest decision of the C++ Committee (last year sometime) is that
> temporaries are destroyed at the end of the full-expression in which
> they are created (unless bound to a reference). A "full-expression" is
> an expression which is not part of any other expression. Not all compilers
> implement this rule yet, and may follow the old rule. The old rule
> allowed destroying the temp at any time up to the end of the block.

And this rule, in the absence of blocks, leads to exactly the bug described
here.  I suspect that the compiler supplier was not deluded, but simply making
a comment either on how they were misled, or on when the change would be
inserted into their compiler.

> It should not be possible to write well-formed code in which a temporary
> is destroyed which was not created. Either the compiler did not catch
> an error in the code, or the compiler did not properly keep track of
> its temporaries. (The compiler is not required to catch all errors in
> code; some constructs have undefined behavior and allowing your program
> to crash is one alternative open to the compiler.)
>
> To be fair, keeping track of the temps is very difficult,
> and most compilers have historically had bugs in that area.

Most certainly every compiler I have ever seen that that tried to do late
destruction has had such bugs.  Those that did early destruction did just fine.
I believe that the ANSI committee understood this quite well when they
made their determination.

Mike Ball
SunSoft