none
Return Methods and the GC RRS feed

  • Question

  • Hi.
    I have a question about writing return methods.
    If you write a method like this:

    public bool ReturnMethod()
    {
        object obj = new object() // Instance the object

        // Return a value
        return true;
    }

    will the 'obj' variable be kept in the memory until you close the application or will the GC take care of it even if you don't dispose it?

    Thanks.
    Friday, June 13, 2008 8:28 PM

Answers

  • The GC couldn't care less whether you implement IDisposable or not.

    Regardless of whether you implement IDisposable, when your object is not referenced, it is subject to garbage collection.  What you could do (and many classes implementing IDisposable do that) is implement a finalizer, which is something the GC is aware of.
    Sasha Goldshtein | http://blogs.microsoft.co.il/blogs/sasha
    • Proposed as answer by curt at amotif Monday, June 16, 2008 7:53 PM
    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Saturday, June 14, 2008 7:58 AM
  • Since obj is a local to the method,  i.e. it is not referenced outside the method,  it will be available for collection immediately after the method call.

    When this obj will be actually collected by GC can not determined (unless you force the GC). It all depends on the available memory, if CLR needs memory, GC might collect this object.

    If you implement the finalizer in your object, collection of your object might be delayed as GC separately maintains finalize queue for those objects having a finalize method.

    If you are having some unmanaged resources and you want to have a provision to release even before the finalize method is called, one of the design pattern is to implement the IDispose interface.

    For further information, you might want to read the following article.

    http://msdn.microsoft.com/en-us/library/b1yfkh5e(VS.71).aspx


    Thanks,

    Tariq A Karim (http://moplah.blogspot.com)
    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Saturday, June 14, 2008 11:11 AM
  • The GC will eventually collect all objects that are not referenced.  Since obj goes out of scope in your example method without being stored anywhere, it will eventually be collected.

    If the object is of a type that implements IDisposable, you should call Dispose on it.  It is not guaranteed that the garbage collector will fully reclaim IDisposable objects if you did not call Dispose on them.
    • Proposed as answer by Jason Kresowaty Saturday, June 14, 2008 12:01 AM
    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Friday, June 13, 2008 11:55 PM
  • Actually it's guaranteed that the GC will not take care of any resources for an object implementing IDisposable. However, if the person who wrote the class implemented the dispose pattern correctly, the resources will be disposed of regardless of whether the caller calls Dispose or not. Furthermore, the caller should call Dispose to free the resource as soon as possible because the resources that are disposed of in this pattern are usually of the finite variety.

    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Saturday, June 14, 2008 12:53 AM

All replies

  • The GC will eventually collect all objects that are not referenced.  Since obj goes out of scope in your example method without being stored anywhere, it will eventually be collected.

    If the object is of a type that implements IDisposable, you should call Dispose on it.  It is not guaranteed that the garbage collector will fully reclaim IDisposable objects if you did not call Dispose on them.
    • Proposed as answer by Jason Kresowaty Saturday, June 14, 2008 12:01 AM
    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Friday, June 13, 2008 11:55 PM
  • Actually it's guaranteed that the GC will not take care of any resources for an object implementing IDisposable. However, if the person who wrote the class implemented the dispose pattern correctly, the resources will be disposed of regardless of whether the caller calls Dispose or not. Furthermore, the caller should call Dispose to free the resource as soon as possible because the resources that are disposed of in this pattern are usually of the finite variety.

    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Saturday, June 14, 2008 12:53 AM
  • The GC couldn't care less whether you implement IDisposable or not.

    Regardless of whether you implement IDisposable, when your object is not referenced, it is subject to garbage collection.  What you could do (and many classes implementing IDisposable do that) is implement a finalizer, which is something the GC is aware of.
    Sasha Goldshtein | http://blogs.microsoft.co.il/blogs/sasha
    • Proposed as answer by curt at amotif Monday, June 16, 2008 7:53 PM
    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Saturday, June 14, 2008 7:58 AM
  • Since obj is a local to the method,  i.e. it is not referenced outside the method,  it will be available for collection immediately after the method call.

    When this obj will be actually collected by GC can not determined (unless you force the GC). It all depends on the available memory, if CLR needs memory, GC might collect this object.

    If you implement the finalizer in your object, collection of your object might be delayed as GC separately maintains finalize queue for those objects having a finalize method.

    If you are having some unmanaged resources and you want to have a provision to release even before the finalize method is called, one of the design pattern is to implement the IDispose interface.

    For further information, you might want to read the following article.

    http://msdn.microsoft.com/en-us/library/b1yfkh5e(VS.71).aspx


    Thanks,

    Tariq A Karim (http://moplah.blogspot.com)
    • Marked as answer by jack 321 Wednesday, June 18, 2008 2:57 AM
    Saturday, June 14, 2008 11:11 AM
  • Tariq A Karim said:

    If you implement the finalizer in your object, collection of your object might be delayed as GC separately maintains finalize queue for those objects having a finalize method.



    I don't believe this is technically correct--the object is still collected as before, when a GC occurs and it's determined that there are no rooted references to the object. It's the finalization that doesn't happen immediately, as the collected finalizable object is put on the freachable queue to be finalized. It's a minor distinction, but I think it's an important one when we're talking about whether an object has been finalized.
    Curt - http://www.codeneverwritten.com/
    Monday, June 16, 2008 7:59 PM
  • Tariq A Karim said:

    Since obj is a local to the method,  i.e. it is not referenced outside the method,  it will be available for collection immediately after the method call.

    Actually it's available for collection sooner than that in an optimised (release) build. It is eligible for collection after the last instruction that could reference it has been executed. This means that it is eligible for collection inside a method after its last use, and is even eligible for collection while methods are executing on the object itself as long as there are no remaining instructions in the method that access instance state.


    http://gregbeech.com/blogs/tech
    Monday, June 16, 2008 9:54 PM
  • Reclaiming the memory used by objects with Finalize methods requires at least two garbage collections. When the garbage collector performs a collection, it reclaims the memory for inaccessible objects without finalizers. At this time, it cannot collect the inaccessible objects that do have finalizers. Instead, it removes the entries for these objects from the finalization queue and places them in a list of objects marked as ready for finalization. Entries in this list point to the objects in the managed heap that are ready to have their finalization code called. The garbage collector calls the Finalize methods for the objects in this list and then removes the entries from the list. A future garbage collection will determine that the finalized objects are truly garbage because they are no longer pointed to by entries in the list of objects marked as ready for finalization. In this future garbage collection, the objects' memory is actually reclaimed.

    For further information, Read the following article:

    http://msdn.microsoft.com/en-us/library/0s71x931(VS.71).aspx


    Thanks,

    Tariq A Karim (http://moplah.blogspot.com)

    Monday, June 16, 2008 10:08 PM
  • May I summarize what I've read so far...

    1) Objects are eligable for GC when they are no longer referenced.  A local variable going out of scope is one way that happens (there are others).
    2) Some resources are NOT recovered by the GC per se.  If the programmer does not release the resource (or make provision for its release) it won't be.
    3) The "design pattern" recommended in this thread (and articles cited) is two pronged; a) if your class acquires resources GC doesn't manage, implement the IDisposable interface, and b) along with IDisposable, implement finalization so that GC can collect those special resources.
    4) Finalization is implemented with a special queue, so there are delays in the actual release of the resource and some performance penalty to pay.
    4) Tariq cites two "must read" articles on GC - thank you.


    Tuesday, June 17, 2008 12:01 AM
  • Tariq, the Finalize methods (i.e. the finalizers) are not called by the garbage collector.  In fact, if they were called during a GC cycle, you'd have a multitude of problems, some obvious and some very subtle (e.g. what if the finalizer triggers another GC by allocating).  Finalizers are called by a separate finalizer thread, which does nothing but call finalizers.
    Sasha Goldshtein | http://blogs.microsoft.co.il/blogs/sasha
    Tuesday, June 17, 2008 7:11 AM
  • Sasha,
    But this is what MSDN says...
    "The garbage collector calls the Finalize methods for the objects in this list and then removes the entries from the list."

    See http://msdn.microsoft.com/en-us/library/0s71x931(VS.71).aspx
    Tuesday, June 17, 2008 12:38 PM
  • You could circumvent this semantic issue by saying that the finalizer thread "is part" of the garbage collector.  However, finalizers are nonetheless called on a separate thread, after garbage collection has completed.  During a garbage collection cycle (at the sweep phase at least) all threads executing managed code, including the finalizer, are suspended.

    You can easily check which thread is executing the finalizer and see for yourself.


    Sasha Goldshtein | http://blogs.microsoft.co.il/blogs/sasha
    Tuesday, June 17, 2008 2:11 PM
  • Regarding the original question:

    will the 'obj' variable be kept in the memory until you close the application or will the GC take care of it even if you don't dispose it?

    In the context of your specific example we don't know the answer. It may be collected before the method returns, or it may be collected later.1 That's a feature of the managed heap, that freeing the memory is non-deterministic. A collection will occur when there's no more managed heap to allocate. You can try to hasten the process by calling GC.Collect, but there's plenty in the literature to explain why that's generally an ugly thing to do.

    The IDisposable pattern and finalizers provide more reliable means of freeing non-memory resources, the finalizer being the far less deterministic of the two. (IDisposable being far more useful than just for freeing things.) I have to agree with Sasha and I would not say the garbage collector calls the Finalize method regardless of what the MSDN topic says. The finalizer runs on a separate thread.

    Anyone with doubts about how this stuff works would do themselves a huge favor if they would buy, read, and comprehend Jeffrey Richter's book CLR via C# second edition. This is an excellent book through and through. Chapter 20 specifically covers managed heap allocation, collection, and finalization.

    Tariq, I think for the purposes of this thread--"when is the memory freed?"--you're correct. I lost track of which thread I was reading and my brain was stuck on finalizers.


    1
    What if your object is never collected, its memory never freed? Do you care? Is the CLR under any obligation to free the object's memory at application shutdown? Why would it--after shutdown you can't reuse that memory anyway. The CLR follows up on an obligation to finalize your finalizable objects, but why waste the cycles freeing memory on application shutdown? :)


    Curt - http://www.codeneverwritten.com/
    Tuesday, June 17, 2008 3:43 PM