Store 'this' at finalization
Asked Answered
W

4

5

How could be defined a code that store 'this' during class finalization? How the garbage collector should behave (if defined somewhere)?

In my mind the GC should finalize multiple times the class instance, and the following test application shall print "66", but the finalizer is executed only once, causing the application to print "6".

Few lines of code:

using System;

namespace Test
{
    class Finalized
    {
        ~Finalized()
        {
            Program.mFinalized = this;
        }

        public int X = 5;
    }

    class Program
    {
        public static Finalized mFinalized = null;

        static void Main(string[] args)
        {
            Finalized asd = new Finalized();
            asd.X = 6;
            asd = null;
            GC.Collect();

            if (mFinalized != null)
                Console.Write("{0}", mFinalized.X);

            mFinalized = null;
            GC.Collect();

            if (mFinalized != null)
                Console.Write("{0}", mFinalized.X);
        }
    }
}

What I'm trying to do is to understand how finalizers manage instance memory. In my application could be desiderable to re-use instance reference again for further processing.

It's clear that the finalizer doesn't "free" memory (at least in my test application). May the memory chunk be reused for other purposes? Or even freed? And if it isn't, that would be a memory leak or what?

Now, I'm confused more than before.

Washer answered 16/8, 2012 at 23:28 Comment(2)
In my experience, you're always doing something wrong if you're using finalizers. I know there are situations where using a finalizer is necessary, but I can't think of any situation where you would write to the console (or do anything with visible side effects) in the finalizer.Socialization
@KendallFrey: always is always wrong, not finalizers. Even if I agree with you, my case obliged me to investigate about it.Washer
Y
8

This is due to Resurrection. By storing the object in another variable during finalization (assigning this to a variable), you resurrect the obejct instance as far as the GC is concerned. You are allowed to resurrect your object in .NET, and you can actually cause the GC to finalize the object more than once, but you have to explicitly request it via GC.ReRegisterForFinalize .

For details, see Automatic Memory Management in the Microsoft .NET Framework.

Yesteryear answered 16/8, 2012 at 23:32 Comment(0)
K
4

GC.Collect does a sweep, special-casing any objects with a finalizer and not collecting them. Once these finalizer objects have finalized, GC then runs again over these objects. If they're no longer eligible for collection (by re-rooting, as you do), so be it. Normally the finalizer only runs once, but IIRC, you can request that it runs again.

Kleptomania answered 16/8, 2012 at 23:34 Comment(0)
I
0

I'm interested in any good uses of resurrected objects.

The MSDN states "There are very few good uses of resurrection, and you really should avoid it if possible". Also Bill Wagner in his Effective C# says "You cannot make this kind of construct work reliably. Dont try". But the book is 2 years old so maybe something changed?

Itching answered 16/8, 2012 at 23:32 Comment(1)
Since the Freachable Queue is a rooted object, ALL finalizable objects are resurrected before the end of the GC cycle where they would otherwise be destroyed. Once the finalizer is run, the entry in the FReachable Queue will be removed, and if no other rooted reference exists the object will again be dead. Between the time the object is found to have no references and the time its finalizer runs, however, the object will--as far as the GC is concerned--be fully alive.Punctilious
S
0

Finalizer only gets called once. You're free to assign self to somewhere, and prevent the object being garbage collected. But once the object is available again for GC, it doesn't run the finalizer.

Sequestration answered 16/8, 2012 at 23:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.