Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Special case lifetime analysis

Suppose I have

void foo () {
    Bar bar = new Bar(); // bar is never referred to after this line
    // (1)
    doSomethingWithoutBar();
}

At (1), is the object bar is pointing to eligible for garbage collection? Or does bar have to fall out of scope as well? Does it make a difference if GC.Collect is called by doSomethingWithoutBar?

This is relevant to know if Bar has a (C#) destructor or something funky like that.

like image 844
Thomas Eding Avatar asked Jul 13 '12 21:07

Thomas Eding


4 Answers

Objects can become eligible for garbage collection as soon as it's certain that they will no longer be used. It's entirely possible that bar will be garbage collected before the variable goes out of scope.

Proof:

using System;

class Bar
{
    ~Bar() { Console.WriteLine("Finalized!"); }
}

class Program
{
    static void Main(string[] args)
    {
        Bar bar = new Bar();
        GC.Collect();
        GC.WaitForPendingFinalizers();
        Console.WriteLine("Press any key to exit...");
        Console.ReadLine();
    }
}

Run in Release Mode (because it doesn't get collected in Debug Mode).

Output:

Finalized!
Press any key to exit...

It also works on ideone which uses Mono. The output is the same.

like image 137
Mark Byers Avatar answered Oct 23 '22 07:10

Mark Byers


Marc answered the question, but here is the solution:

void foo () {
    Bar bar = new Bar(); // bar is never referred to after this line
    // (1)
    doSomethingWithoutBar();

    GC.KeepAlive(bar); // At the point where you no longer need it
}
like image 36
Tergiver Avatar answered Oct 23 '22 07:10

Tergiver


From a quick reading of the spec, it looks like it's implementation specific. It's allowed to garbage collect it, but not required to.

I get this from a note in section 10.9 "Automatic Memory Management" of the ECMA Spec:

[Note: Implementations might choose to analyze code to determine which references to an object can be used in the future. For instance, if a local variable that is in scope is the only existing reference to an object, but that local variable is never referred to in any possible continuation of execution from the current execution point in the procedure, an implementation might (but is not required to) treat the object as no longer in use. end note]

Emphasis mine.

like image 36
Paul Phillips Avatar answered Oct 23 '22 08:10

Paul Phillips


Without defining what version of the CLR you're referring to, it's impossibledifficult to be definitive about the behaviour that you'll see here.

A hypothetical CLR could, in this example, assuming that the following is true:

  1. The constructor for Bar does nothing
  2. There are no fields that are initialised (i.e. there are no potential side-effects to the objects construction)

Entirely disregard the line Bar bar = new Bar(); and optimise it away as it "does nothing".

As far as my memory serves, in current versions of the CLR bar is eligible for garbage collection the moment after you've constructed it.

like image 40
Rob Avatar answered Oct 23 '22 08:10

Rob