none
Garbage Collection Issue RRS feed

  • Question

  • Hi,
        I had a question regarding Grabage Collection in C#.

        Suppose there are two objects Obj1 and Obj2. Obj1 holds a reference to Obj2. Suppose both Obj1 and Obj2 are not at all refered in the applicaiton else where. Now in this case Obj1 will be a candidate for garbage collection as nobody else holds the reference for Obj1. But Obj2 will not be grabage collected as Obj1 still holds a reference to it.
        Is this a correct assumption? 
        Or both the object will be garbage collected as there is no reference to both of them in the active application flow?

        What if Obj1 has a reference to Obj2 and Obj2 also has a reference to Obj1, and none of them is referend by the application anywhere. Will both of them be considerd for Garbage collection?

        Is it necessary that object should be refernced by the main application flow? Or even any reference is considerd as active reference and then the object is igored for garbage collection.

    -Saurabh.
    Saurabh Surana
    Thursday, June 5, 2008 12:51 PM

Answers

  • Hi Saurabh,

    > Suppose there are two objects Obj1 and Obj2. Obj1 holds a reference to Obj2. Suppose both Obj1 and Obj2 are not at all refered in the applicaiton > else where. Now in this case Obj1 will be a candidate for garbage collection as nobody else holds the reference for Obj1. But Obj2 will not be
    > grabage collected as Obj1 still holds a reference to it.
    >    Is this a correct assumption? 

    No, GC always tries to find if particular object is accessible from application roots (Application roots include include global and static object pointers, local variables, reference object parameters on thread's stack, and CPU registers). Since Obj1 is not reachable from root, then Obj2 is also not reachable.

    > What if Obj1 has a reference to Obj2 and Obj2 also has a reference to Obj1, and none of them is referend by the application anywhere. Will both of > them be considerd for Garbage collection?

    Yes


    Vitaliy Liptchinsky
    Thursday, June 5, 2008 1:09 PM

All replies

  • Hi Saurabh,

    > Suppose there are two objects Obj1 and Obj2. Obj1 holds a reference to Obj2. Suppose both Obj1 and Obj2 are not at all refered in the applicaiton > else where. Now in this case Obj1 will be a candidate for garbage collection as nobody else holds the reference for Obj1. But Obj2 will not be
    > grabage collected as Obj1 still holds a reference to it.
    >    Is this a correct assumption? 

    No, GC always tries to find if particular object is accessible from application roots (Application roots include include global and static object pointers, local variables, reference object parameters on thread's stack, and CPU registers). Since Obj1 is not reachable from root, then Obj2 is also not reachable.

    > What if Obj1 has a reference to Obj2 and Obj2 also has a reference to Obj1, and none of them is referend by the application anywhere. Will both of > them be considerd for Garbage collection?

    Yes


    Vitaliy Liptchinsky
    Thursday, June 5, 2008 1:09 PM
  • Thanks for the reply Vitaliy.
        
    Can you tell me If I call System.GC.Collect(), is it guaranteed that Garbage Collection will happen at that point?

    Is it good practice to call System.GC.Collect(2,GCCollectionMode.Forced) to force a garbage collection of Generation 2 Objects?
    (Actually I am calling this after the closing of a form which is supposed to be very heavy one)

    The reason I ma calling GC for Generation 2 is, somewhere I read that when GC for Generation 2 is called the objects finalize method is called and they are garbage collected in one go. If we call GC for any lower generation, in the first run of GC finalize of the obejcts will be called and then next time they will be garbage collected.
    I want this GC to happen immediately as it is expected to release huge amount of memory.



    Saurabh Surana
    Thursday, June 5, 2008 1:36 PM
  • I actually used CLR Profiler on my application.
    When I close that perticular form, it shows me a node "Finalize" which is connected to a custome control of the form, that node is connected to the form node.

    So from this I got a feeling that some how that custom control's finalize method has been called and it is waiting for the next GC cycle where it will get cleaned up.

    Is it a correct assumption?

    Because of this I don't want GC to call finalize in first run and the collect the object in second run. I wan it to do both the task in one go.
    Can you tell me other option by which I can achieve this?

    Saurabh Surana
    Thursday, June 5, 2008 1:42 PM
  • Yes, GC.Collect forces immediate garbage collection of all generations. Usually it is strongly recommended to avoid calling of GC.Collect (and GC.Collect(2,GCCollectionMode.Forced) in particular) because it can impact application performance in negative way, but there is always exceptions.  If you do not have valid reasons to call GC.Collect method, then don't do it.

    During garbage collection GC places all unreachable objects that has Finalizer method into special queue, called freachable. After this special finalization thread performs calls of all Finalize methods in this queue. Objects located in freachable  queue are temporarily considered to be reachable. Called again GC finds out that finalized objects from freachable queue again became garbage and removes them from memory.
    Vitaliy Liptchinsky
    Thursday, June 5, 2008 2:49 PM
  • In other words, you'd have to call GC.Collect(), GC.WaitForPendingFinalizers(), then GC.Collect() again.  The latter collect ensures that objects referenced by objects with finalizers are collected. 

    But really, avoid this at all possible cost.  You'll put objects into generation #1, possibly even #2 that will get stuck there for quite a while.  Without the collect calls, they'd stay in #0 and get collected on the next sweep.

    Hans Passant.
    Thursday, June 5, 2008 11:44 PM
    Moderator