stack variables that don't die?

Discussion in 'C++' started by Dougan, Oct 17, 2006.

  1. Dougan

    Dougan Guest

    I've seen code that allocates an object on the stack and then saves a
    class reference to it.

    example:
    void ScribbleArea::resizeImage( const QSize &newSize)
    {
    QImage newImage( newSize, );
    *m_image = newImage; // m_image is a QImage
    }

    Now, when c++ leaves the function, I guess the stack memory for
    newImage
    is not reclaimed, because the object is still referenced?

    If this is correct, when, if ever. is the memory in the stack
    reclaimed?

    If this function were called many times, woudn't this lead to
    leaks in the stack, if that is possible?
    Dougan, Oct 17, 2006
    #1
    1. Advertising

  2. Dougan

    Ian Collins Guest

    Dougan wrote:
    > I've seen code that allocates an object on the stack and then saves a
    > class reference to it.
    >
    > example:
    > void ScribbleArea::resizeImage( const QSize &newSize)
    > {
    > QImage newImage( newSize, );
    > *m_image = newImage; // m_image is a QImage
    > }
    >
    > Now, when c++ leaves the function, I guess the stack memory for
    > newImage
    > is not reclaimed, because the object is still referenced?
    >

    No, it will be reused, but you have made a copy of it.

    > If this is correct, when, if ever. is the memory in the stack
    > reclaimed?
    >

    This can't leak memory, you don't use the heap, unless QImage leaks memory.

    --
    Ian Collins.
    Ian Collins, Oct 17, 2006
    #2
    1. Advertising

  3. Dougan

    Dougan Guest

    Thanks very much, I see now where I was confused.
    Dougan, Oct 17, 2006
    #3
  4. Dougan

    Salt_Peter Guest

    Ian Collins wrote:
    > Dougan wrote:
    > > I've seen code that allocates an object on the stack and then saves a
    > > class reference to it.
    > >
    > > example:
    > > void ScribbleArea::resizeImage( const QSize &newSize)
    > > {
    > > QImage newImage( newSize, );
    > > *m_image = newImage; // m_image is a QImage


    no, m_image is a pointer and we don't know if thats an allocated
    pointer.
    newImage is a temporary QImage.

    > > }
    > >
    > > Now, when c++ leaves the function, I guess the stack memory for
    > > newImage
    > > is not reclaimed, because the object is still referenced?
    > >

    > No, it will be reused, but you have made a copy of it.


    Are you sure? What if the member pointer was never allocated? That
    would be a copy into unreserved memory. So between resizes, the
    temporary image would be copied into unprotected memory?
    Please tell me i'm wrong. Otherwise, thats undefined behaviour and one
    very nasty bug to crack.

    >
    > > If this is correct, when, if ever. is the memory in the stack
    > > reclaimed?
    > >

    > This can't leak memory, you don't use the heap, unless QImage leaks memory.
    >
    > --
    > Ian Collins.
    Salt_Peter, Oct 17, 2006
    #4
  5. Dougan

    Ian Collins Guest

    Salt_Peter wrote:
    > Ian Collins wrote:
    >
    >>Dougan wrote:
    >>
    >>>
    >>>Now, when c++ leaves the function, I guess the stack memory for
    >>>newImage
    >>>is not reclaimed, because the object is still referenced?
    >>>

    >>
    >>No, it will be reused, but you have made a copy of it.

    >
    >
    > Are you sure? What if the member pointer was never allocated? That
    > would be a copy into unreserved memory. So between resizes, the
    > temporary image would be copied into unprotected memory?
    > Please tell me i'm wrong. Otherwise, thats undefined behaviour and one
    > very nasty bug to crack.
    >

    Who knows? I was assuming the pointer was valid and the OP was simply
    replacing the object. Otherwise the operation does invoke UB.


    --
    Ian Collins.
    Ian Collins, Oct 17, 2006
    #5
  6. Dougan

    Salt_Peter Guest

    Ian Collins wrote:
    > Salt_Peter wrote:
    > > Ian Collins wrote:
    > >
    > >>Dougan wrote:
    > >>
    > >>>
    > >>>Now, when c++ leaves the function, I guess the stack memory for
    > >>>newImage
    > >>>is not reclaimed, because the object is still referenced?
    > >>>
    > >>
    > >>No, it will be reused, but you have made a copy of it.

    > >
    > >
    > > Are you sure? What if the member pointer was never allocated? That
    > > would be a copy into unreserved memory. So between resizes, the
    > > temporary image would be copied into unprotected memory?
    > > Please tell me i'm wrong. Otherwise, thats undefined behaviour and one
    > > very nasty bug to crack.
    > >

    > Who knows? I was assuming the pointer was valid and the OP was simply
    > replacing the object. Otherwise the operation does invoke UB.
    > --
    > Ian Collins.


    After verification and for the record, Qt's recommendation is to have
    class ScribbleArea hold a QImage component, not a pointer. Now that
    makes sense to me if QImage has the appropriate copy constructor. Hmm.
    http://doc.trolltech.com/4.1/widgets-scribble-scribblearea-h.html

    To the OP, pointers - unless proven otherwise - point to nothing at all.
    Salt_Peter, Oct 17, 2006
    #6
  7. Dougan

    Kaz Kylheku Guest

    Dougan wrote:
    > I've seen code that allocates an object on the stack and then saves a
    > class reference to it.


    Does it?

    >
    > example:
    > void ScribbleArea::resizeImage( const QSize &newSize)
    > {
    > QImage newImage( newSize, );
    > *m_image = newImage; // m_image is a QImage
    > }


    This can't possibly save a reference, unless m_image is a pointer to a
    class object which has an overloaded assignment operator (a member or
    non-member one). That is to say:

    // Suppose this is m_image:
    SomeObject *m_image;

    // And suppose this the assignment op
    void SomeObject::eek:perator = (QImage &ref);

    Similarly, m_image could be a smart pointer rather than an ordinary
    pointer, with the same effect.

    The only other way a reference could be taken would be if the
    expression *m_image were in fact a reference. That would mean that
    m_image is a pointer to a reference. But, you probably know that there
    is no such thing in C++: you can't point at a reference.

    > Now, when c++ leaves the function, I guess the stack memory for
    > newImage
    > is not reclaimed, because the object is still referenced?


    The C++ language does not have lexical closures, nor does the C++
    standard mandate the support for garbage collection. Any use of an
    non-static local object whose scope has terminated is undefined
    behavior.

    The C++ language does require the destructors to be called.

    > If this is correct, when, if ever. is the memory in the stack
    > reclaimed?


    The destructors, if any, are called when the activation associated with
    the enclosing block scope terminates. The memory can be reclaimed any
    time after that, and typically that is done right away, since in the
    typical C++ implementation, a simple linear stack is in fact used as
    the basis for automatic storage.

    > If this function were called many times, woudn't this lead to
    > leaks in the stack, if that is possible?


    In languages which allow local variables to endure after the
    termination of the enclosing block, this problem is taken care of by
    garbage collection (or in less mature technology of that ilk, by
    reference counting).

    Note that in these languages, such as Scheme or Common Lisp, there
    aren't any pointers. So the only way you can actually access a variable
    in a block scope which has terminated is to invoke a closure which was
    created in that block. The closure internally holds a reference to a
    piece of code, and a reference to the environment frame which was saved
    (the piece of the stack that was "leaked", but not really). That frame
    pointer allows the closure to reference the variables.

    In these languages, therefore, support for closures is the only reason
    why variable bindings survive block scope termination. Good compilers
    for these languages analyze and optimize closures. When closures are
    not used in a function at all, all of its local storage can be
    allocated on a stack, just like in C or C++, which can be a major
    performance gain: if you don't use it, you don't pay for it. But even
    if closures are present, this optimization may still be possible if the
    closures are not escaping: the closures are only passed down into code
    but not returned (in jargon, the code uses downward funargs only).
    Closures which are not passed anywhere can even be refactored locally
    and disappear. E.g. (funcall (lambda (x) (print x)) 42) is the same as
    (let ((x 42)) (print x)) which can be hacked all the way down to (print
    42).
    Kaz Kylheku, Oct 17, 2006
    #7
  8. Dougan

    Salt_Peter Guest

    Ian Collins wrote:
    > Salt_Peter wrote:
    > > Ian Collins wrote:
    > >
    > >>Dougan wrote:
    > >>
    > >>>
    > >>>Now, when c++ leaves the function, I guess the stack memory for
    > >>>newImage
    > >>>is not reclaimed, because the object is still referenced?
    > >>>
    > >>
    > >>No, it will be reused, but you have made a copy of it.

    > >
    > >
    > > Are you sure? What if the member pointer was never allocated? That
    > > would be a copy into unreserved memory. So between resizes, the
    > > temporary image would be copied into unprotected memory?
    > > Please tell me i'm wrong. Otherwise, thats undefined behaviour and one
    > > very nasty bug to crack.
    > >

    > Who knows? I was assuming the pointer was valid and the OP was simply
    > replacing the object. Otherwise the operation does invoke UB.
    >
    >
    > --
    > Ian Collins.


    After verification and for the record, Qt's recommendation is to have
    class ScribbleArea hold a QImage component, not a pointer. Now that
    makes sense to me if QImage has the appropriate assignment operator.
    Hmm.
    http://doc.trolltech.com/4.1/widgets-scribble-scribblearea-h.html

    To the OP, pointers - unless proven otherwise - point to nothing at all.
    Salt_Peter, Oct 17, 2006
    #8
    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. Lloyd Sheen

    Die IDE Die

    Lloyd Sheen, Jan 24, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    429
    Natty Gur
    Jan 26, 2004
  2. Lloyd Sheen

    More Die IDE Die

    Lloyd Sheen, Jan 24, 2004, in forum: ASP .Net
    Replies:
    5
    Views:
    447
    Alvin Bruney
    Jan 25, 2004
  3. Surinder Singh
    Replies:
    1
    Views:
    1,198
    Richard Bos
    Dec 20, 2007
  4. Casey Hawthorne
    Replies:
    3
    Views:
    1,090
    Flash Gordon
    Nov 1, 2009
  5. Debajit Adhikary
    Replies:
    36
    Views:
    2,293
    Andre Kaufmann
    Feb 10, 2011
Loading...

Share This Page