cast to non-const reference of a function's return object

Discussion in 'C++' started by klaus triendl, Jun 2, 2004.

  1. hi,

    recently i discovered a memory leak in our code; after some investigation i
    could reduce it to the following problem:
    return objects of functions are handled as temporary objects, hence their
    dtor is called immediately and not at the end of the function. to be able to
    use return objects (to avoid copying) i often assign them to a const
    reference.
    now, casting a const return object from a function to a non-const reference
    to this return object calls immediately the dtor of the return object
    anyway, any further operation deals with a non-valid object then. if i do
    this in two steps - first holding a const reference to the return object and
    then const_casting it, everything works like i expected it.

    does anybody know whether the compiler behaves correctly?


    i use the following short example to illustrate my question:

    const string getastring()
    {
    return string();
    }

    void funcWmemleak()
    {
    string& str = const_cast<string&>(getastring());
    str = "test"; // this is already an invalid object because the dtor was
    called before (and won't ever be called again of course)
    }

    void funcWOmemleak()
    {
    const string& str1 = getastring();
    string& str = const_cast<string&>(str1);
    str = "test";
    }

    int main()
    {
    funcWmemleak();
    funcWOmemleak();
    }





    --
    klaus triendl
    klaus triendl, Jun 2, 2004
    #1
    1. Advertising

  2. klaus triendl

    tom_usenet Guest

    On Wed, 02 Jun 2004 08:09:01 GMT, "klaus triendl" <>
    wrote:

    >hi,
    >
    >recently i discovered a memory leak in our code;


    I think you mean "use of a dangling reference" rather than "memory
    leak".

    after some investigation i
    >could reduce it to the following problem:
    >return objects of functions are handled as temporary objects, hence their
    >dtor is called immediately and not at the end of the function. to be able to
    >use return objects (to avoid copying) i often assign them to a const
    >reference.
    >now, casting a const return object from a function to a non-const reference
    >to this return object calls immediately the dtor of the return object
    >anyway, any further operation deals with a non-valid object then. if i do
    >this in two steps - first holding a const reference to the return object and
    >then const_casting it, everything works like i expected it.
    >
    >does anybody know whether the compiler behaves correctly?


    Yes, binding a temporary directly to a const reference extends the
    lifetime of the temporary to match that of the reference. You can't
    bind a temporary to a non-const reference, so there's no way of doing
    the lifetime extension using a non-const ref.

    Note, since you return a const string, using the returned string as a
    non-const string results in undefined behaviour. You can only safely
    use an object that has had const cast away as a non-const object if it
    wasn't originally declared const.

    Tom
    --
    C++ FAQ: http://www.parashift.com/c -faq-lite/
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    tom_usenet, Jun 2, 2004
    #2
    1. Advertising

  3. "tom_usenet" <> wrote in message
    news:<>...
    > On Wed, 02 Jun 2004 08:09:01 GMT, "klaus triendl" <>
    > wrote:
    >
    > >hi,
    > >
    > >recently i discovered a memory leak in our code;

    >
    > I think you mean "use of a dangling reference" rather than "memory
    > leak".

    in our code the returned object is a reference counting pointer and the
    string "test" is a new object which is not freed causing a memory leak
    (reported by the debugger as such).

    > after some investigation i
    > >could reduce it to the following problem:
    > >return objects of functions are handled as temporary objects, hence their
    > >dtor is called immediately and not at the end of the function. to be able

    to
    > >use return objects (to avoid copying) i often assign them to a const
    > >reference.
    > >now, casting a const return object from a function to a non-const

    reference
    > >to this return object calls immediately the dtor of the return object
    > >anyway, any further operation deals with a non-valid object then. if i do
    > >this in two steps - first holding a const reference to the return object

    and
    > >then const_casting it, everything works like i expected it.
    > >
    > >does anybody know whether the compiler behaves correctly?

    >
    > Yes, binding a temporary directly to a const reference extends the
    > lifetime of the temporary to match that of the reference. You can't
    > bind a temporary to a non-const reference, so there's no way of doing
    > the lifetime extension using a non-const ref.

    if the temporary is non-const i can bind it to a non-const reference. at
    least with vc++7 it is possible.

    > Note, since you return a const string, using the returned string as a
    > non-const string results in undefined behaviour. You can only safely
    > use an object that has had const cast away as a non-const object if it
    > wasn't originally declared const.

    well, that's an argument; and i can easily solve that problem.
    but my question still remains whether the const_cast in the function
    "funcWmemleak" is a good reason that the non-const reference is a non-valid
    object after the assignment or not.



    --
    klaus triendl
    klaus triendl, Jun 2, 2004
    #3
  4. klaus triendl

    tom_usenet Guest

    On Wed, 02 Jun 2004 14:07:20 GMT, "klaus triendl" <>
    wrote:

    >> Yes, binding a temporary directly to a const reference extends the
    >> lifetime of the temporary to match that of the reference. You can't
    >> bind a temporary to a non-const reference, so there's no way of doing
    >> the lifetime extension using a non-const ref.

    >if the temporary is non-const i can bind it to a non-const reference. at
    >least with vc++7 it is possible.


    This is a non-conforming compiler extension. On VC7.1 I get a warning,
    and compiling with /Za (ISO mode) I get an error.

    >
    >> Note, since you return a const string, using the returned string as a
    >> non-const string results in undefined behaviour. You can only safely
    >> use an object that has had const cast away as a non-const object if it
    >> wasn't originally declared const.

    >well, that's an argument; and i can easily solve that problem.


    Indeed, that paragraph was just an aside.

    >but my question still remains whether the const_cast in the function
    >"funcWmemleak" is a good reason that the non-const reference is a non-valid
    >object after the assignment or not.


    If you perform the const_cast, then you are not directly binding the
    reference to the temporary, and the lifetime will not be extended,
    hence you have a "dangling reference" that you can't use. It is
    synonymous to this conforming code that exhibits the same problem, and
    doesn't use any Microsoft extensions:

    #include <string>
    #include <iostream>
    using namespace std;

    int main()
    {
    string const& s = static_cast<string const&>(string("foo"));
    cout << s << '\n';
    }

    Because s isn't bound directly to the temporary (it is bound to the
    result of the static cast), it doesn't extend the temporary's lifetime
    and the cout call has undefined behaviour since the temporary has
    already been destroyed. Remove the static_cast and it's fine. See
    12.2/5 in the C++ standard.

    Clear?

    Tom
    --
    C++ FAQ: http://www.parashift.com/c -faq-lite/
    C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
    tom_usenet, Jun 2, 2004
    #4
  5. klaus triendl

    Dave Moore Guest

    "klaus triendl" <> wrote in message news:<salvc.35943$>...

    > > after some investigation i
    > > >could reduce it to the following problem:
    > > >return objects of functions are handled as temporary objects, hence their
    > > >dtor is called immediately and not at the end of the function. to be able

    > to
    > > >use return objects (to avoid copying) i often assign them to a const
    > > >reference.
    > > >now, casting a const return object from a function to a non-const

    > reference
    > > >to this return object calls immediately the dtor of the return object
    > > >anyway, any further operation deals with a non-valid object then. if i do
    > > >this in two steps - first holding a const reference to the return object

    > and
    > > >then const_casting it, everything works like i expected it.
    > > >
    > > >does anybody know whether the compiler behaves correctly?

    > >
    > > Yes, binding a temporary directly to a const reference extends the
    > > lifetime of the temporary to match that of the reference. You can't
    > > bind a temporary to a non-const reference, so there's no way of doing
    > > the lifetime extension using a non-const ref.

    > if the temporary is non-const i can bind it to a non-const reference. at
    > least with vc++7 it is possible.
    >
    > > Note, since you return a const string, using the returned string as a
    > > non-const string results in undefined behaviour. You can only safely
    > > use an object that has had const cast away as a non-const object if it
    > > wasn't originally declared const.

    > well, that's an argument; and i can easily solve that problem.
    > but my question still remains whether the const_cast in the function
    > "funcWmemleak" is a good reason that the non-const reference is a non-valid
    > object after the assignment or not.


    Yes, it is a valid reference until the const reference that the
    temporary was originally bound to is destroyed (i.e. goes out of
    scope), provided that the destructor for the original object is not
    called in the interim (which is highly unlikely given the context).

    HTH, Dave Moore
    Dave Moore, Jun 2, 2004
    #5
  6. > Because s isn't bound directly to the temporary (it is bound to the
    > result of the static cast), it doesn't extend the temporary's lifetime
    > and the cout call has undefined behaviour since the temporary has
    > already been destroyed. Remove the static_cast and it's fine. See
    > 12.2/5 in the C++ standard.
    >
    > Clear?


    clear as glass :)
    thx for the explanation. it's good to know that the compiler considers the
    const_cast a function returning a result.

    and thx to dave moore for your posting.


    klaus
    klaus triendl, Jun 4, 2004
    #6
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Jim Langston
    Replies:
    2
    Views:
    448
    Rolf Magnus
    May 11, 2006
  2. Javier
    Replies:
    2
    Views:
    561
    James Kanze
    Sep 4, 2007
  3. George2
    Replies:
    10
    Views:
    595
    Pete Becker
    Dec 17, 2007
  4. Arv
    Replies:
    15
    Views:
    922
    James Kanze
    Mar 7, 2008
  5. fungus
    Replies:
    13
    Views:
    886
    fungus
    Oct 31, 2008
Loading...

Share This Page