Topic: Q: returning reference to local variable


Author: Stephen.Clamage@sun.com (Steve Clamage)
Date: 1999/03/17
Raw View
sbnaran@localhost.localdomain.COM (Siemel Naran) writes:

>These simple cases -- ie, returning a reference to a local object
>-- could have been made errors.

That's hard to specify in a useful way.

For example, given a function declared to return a T&,
we'd certainly like this to be an error:
    T t;
    ...
    return t;

But what about this:
    T t;
    static T u;
    ...
    return external_condition ? t : u;

And this:
    T t;
    ...
    if( external_condition )
        return t;

And this:
    T t, u, v;
    ...
    if( external_condition_1 )
        return t;
    if( external_condition_2 )
        return u;
    if( ! (external_condition_1 || external_condition_2)  )
        return v;
Flow analysis would show that a reference to some local variable
will always be returned, but should we require that compilers do
that analysis?

If the second or third examples are errors, what about this:
    T t;
    double x;
    ...
    if( sqrt(x) < 0.0 )
        return t;
Do we require that the compiler know that sqrt can't return a
negative number, and so the code is OK? Suppose instead of
sqrt it was some user function in the same translation unit?
Or an inline function? How smart do we require compilers to be?

Instead, the standard leaves the whole thing as a quality of
implementation issue. The behavior is undefined, meaning that a
compiler can report warnings or errors for cases when it can
determine that a reference to an auto object will be returned.
A good compiler will do so for cases like the first example.

--
Steve Clamage, stephen.clamage@sun.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: Stephen.Clamage@sun.com (Steve Clamage)
Date: 1999/03/17
Raw View

Following up my own post with a correction.

Stephen.Clamage@sun.com (Steve Clamage) writes:

>The compiler cannot always detect the error, even in principle.
>Example:

>int& foo(int& k) // in one translation unit
>{
>    static m = 0;
>    cout << "Enter a value >= 0: ";
>    cin >> m;
>    return m < 0 ? k : m;
>}

>int bar() // in a different translation unit
>{
>    int i = 0;
>    return foo(i);
>}

Oops. Gremlins ate a "&". I meant to write

int& bar()
{
    int i = 0;
    return foo(i);
}


>Does bar return a reference to an auto object? It does if the
>program user enters a negative number, which is not supposed
>to happen. In any event, neither bar by itself nor foo by
>itself breaks any rules.

>Many compilers do tell you about cases where the error is
>obvious, however. I would complain to the vendor if the
>compiler did not.

--
Steve Clamage, stephen.clamage@sun.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: "AllanW {formerly AllanW@my-dejanews.com}" <allan_w@my-dejanews.com>
Date: 1999/03/18
Raw View
In article <7cp2km$sqa$1@engnews1.eng.sun.com>,
  Stephen.Clamage@sun.com (Steve Clamage) wrote:
>
> sbnaran@localhost.localdomain.COM (Siemel Naran) writes:
>
> >These simple cases -- ie, returning a reference to a local object
> >-- could have been made errors.
>
> That's hard to specify in a useful way.

It's hard to specify thoroughly. I suspect that it's not as hard to
specify in a way that is at least sometimes useful.

> For example, given a function declared to return a T&,
> we'd certainly like this to be an error:
>     T t;
>     ...
>     return t;

Yes, good idea.

> But what about this:
>     T t;
>     static T u;
>     ...
>     return external_condition ? t : u;
>
> And this:
>     T t;
>     ...
>     if( external_condition )
>         return t;
>
> And this:
>     T t, u, v;
>     ...
>     if( external_condition_1 )
>         return t;
>     if( external_condition_2 )
>         return u;
>     if( ! (external_condition_1 || external_condition_2)  )
>         return v;
> Flow analysis would show that a reference to some local variable
> will always be returned, but should we require that compilers do
> that analysis?

We don't need to do flow analysis to see that these return
statements *might* return a local variable by reference. Any return
statement which potentially returns an lvalue of a local variable
should be an error.

> If the second or third examples are errors, what about this:
>     T t;
>     double x;
>     ...
>     if( sqrt(x) < 0.0 )
>         return t;
> Do we require that the compiler know that sqrt can't return a
> negative number, and so the code is OK?

Absolutely not. If the compiler is capable of doing dead-code
analysis that thoroughly, more power to it. But we can at least
recognize that the return statement, if executed, might do
something invalid.

> Suppose instead of
> sqrt it was some user function in the same translation unit?
> Or an inline function? How smart do we require compilers to be?

You want to prove that there are some cases we can't expect the
compiler to catch? How about this:

    T &badfunc() {
        T localval;
        T*ptr = &localval;
        // ...
        return *ptr;
    }