none
GC doubt RRS feed

  • Question

  •  

    Do we have to explicitly dispose the local objects, objects created in a function? Or when the control comes out of the function that object becomes eligible for GC and will be collected when next cycle of GC is run?

     

    See the code below:

     

    There is class level object objA and local or Function level object objB. Do I need to explicitly dispose the object objB as done in finally block for making it eligible for GC or will the objB will be eligible for GC once the control comes out of this function

     

    Thanks in advance.

     

    Code Snippet

    class SomeClass

    {

             classA objA = new ClassA();

     

             public void SomeMethod()

             {

                classB objB = new ClassB();

                try{}

                catch(){}

                finally

                {

                   if(objB != null)

                     objB  = null;

                }

     

             }

    }

     

     

     

     

     

    Tuesday, April 15, 2008 8:58 AM

Answers

  • Phillipe - the behaviour you describe is what you'll observe in a DEBUG build; the life of variables are extended here for easier debugging.

    It is NOT the behaviour you will observe in a RELEASE build; here variables are eligible for collection as soon as they go out of scope, which is after the last time they are referenced. In a RELEASE build explicitly setting objects to null can potentially extend their lifetime, it cannot reduce it.

    Why do you think GC.KeepAlive() exists? It's to keep a variable that is passed to unmanaged code, and thus doesn't appear to be referenced as far as the GC is aware, alive until that point.
    Tuesday, April 15, 2008 8:12 PM
  • This is not correct.  Setting a reference to null does not affect the GC.  In release mode, the JIT compiler will in fact not generate code for it.  Check this blog post for reference.  As Greg pointed out, GC.KeepAlive() is another major hint.  We wouldn't need it if we could keep a reference alive by just not nulling it.
    Friday, April 18, 2008 2:07 AM
    Moderator

All replies

  • Hello,

     

    you don't need to set objB to null, it will be eligible for GC at the end of the function scope.

     

    It's however perfectly valide to set an object to null if you want to reduce it's life Smile you can also use the { } to reduce a scope.

     

    usualy if you realy need an object to be disposed you need to implement IDisposable interface. you can then run you code analyse tool (fxcop) to see if the implementation is correct.

     

    you can then use the syntax

    using(var myDisposableObject = new ClassB())

    {

    //Do something

    }//<-- call of dispose even if an exception occures.

    Tuesday, April 15, 2008 10:58 AM
  • Hi Mukund,

     

    Peace of code in finally statement is completely redundant. Reference to objB object is allocated in call stack, therefore this reference will be removed after completion of SomeMethod.

     

    If classB implements IDisposable interface, there is sense to use using statement or call Dispose method at the end of SomeMethod or before.

     

    Tuesday, April 15, 2008 1:02 PM
  •  Gomata wrote:

    It's however perfectly valide to set an object to null if you want to reduce it's life you can also use the { } to reduce a scope.

     

    Well, actually, setting a local variable reference to null in the middle of a method can sometimes make sense. Reducing the scope doesn't help, because a local variable that's not longer in scope will remain on the call stack until the method exits.

     

    For example:

     

    Code Snippet

    public void LongRunningMethodA()

    {

       if ( condition )

       {

           BigClass bigObject = new BigClass();

           // ...

       }

     

       // At this point, although "bigObject" is out of scope, it is still on the stack

       // so it will not be garbage collected until the method exits

      

       AnotherLongRunningMethod();

     

       // At this point, "bigObject" is still on the stack,

       // and will not be garbage collected

    }

     

     

    If you know the method will continue to run for a long time, and you want to tell the garbage collector to collect it when "it pleases", you should set the variable to null:

     

    Code Snippet

    public void LongRunningMethodA()

    {

       if ( condition )

       {

           BigClass bigObject = new BigClass();

           // ...

           bigObject = null;

       }

      

       // From here on, bigObject is null, so it's eligable for GC.

     

       AnotherLongRunningMethod();

    }

     

     

     

    Tuesday, April 15, 2008 7:55 PM
  • Phillipe - the behaviour you describe is what you'll observe in a DEBUG build; the life of variables are extended here for easier debugging.

    It is NOT the behaviour you will observe in a RELEASE build; here variables are eligible for collection as soon as they go out of scope, which is after the last time they are referenced. In a RELEASE build explicitly setting objects to null can potentially extend their lifetime, it cannot reduce it.

    Why do you think GC.KeepAlive() exists? It's to keep a variable that is passed to unmanaged code, and thus doesn't appear to be referenced as far as the GC is aware, alive until that point.
    Tuesday, April 15, 2008 8:12 PM
  • Greg, you're right of course, although I don't see why setting a local variable to null would extend its lifetime.

     

    A lot of applications are running a debug build (don't ask me why), so setting a variable to null in a long running method certainly helps the GC do its job.

    Tuesday, April 15, 2008 8:27 PM
  • I think setting object to null in managed C# doesn't make sense. It doesn't matter when GB will destroy object, that doesn't hurt performance, but checking object and setting it to null does,

    greet
    Thursday, April 17, 2008 8:28 AM
  •  Dragoslav Zaric wrote:
    I think setting object to null in managed C# doesn't make sense. It doesn't matter when GB will destroy object, that doesn't hurt performance, but checking object and setting it to null does,

    It makes a lot of sense when memory usage is an issue. The performance hit of setting an object to null is almost zero. If a variable points to a huge object, but you no longer need it, it's better to set it to null, so the GC can collect it. Otherwise, it will remain in memory until the variable goes out of scope or is set to null (or another object).
    Thursday, April 17, 2008 8:38 AM
  • Ok, but GC is triggered a long time before when memory becomes problem ?

    greet
    Thursday, April 17, 2008 9:03 AM
  •  Dragoslav Zaric wrote:
    Ok, but GC is triggered a long time before when memory becomes problem ?

    Yes, unless there is still a reference to a very big object. The GC will not touch it until the object is no longer referenced (which can be forced by setting the variable referencing the object to null)
    Thursday, April 17, 2008 9:36 AM
  • This is not correct.  Setting a reference to null does not affect the GC.  In release mode, the JIT compiler will in fact not generate code for it.  Check this blog post for reference.  As Greg pointed out, GC.KeepAlive() is another major hint.  We wouldn't need it if we could keep a reference alive by just not nulling it.
    Friday, April 18, 2008 2:07 AM
    Moderator
  •  nobugz wrote:
    This is not correct.  Setting a reference to null does not affect the GC.  In release mode, the JIT compiler will in fact not generate code for it.  Check this blog post for reference.  As Greg pointed out, GC.KeepAlive() is another major hint.  We wouldn't need it if we could keep a reference alive by just not nulling it.

    You're right. I was wrong.

    Well, this proves that I am getting smarter by saying wrong things

    Thanks for clarifying!

    Friday, April 18, 2008 7:13 AM