#734 – Accessing the Original Object Referenced through a WeakReference

You can create a WeakReference instance that refers to an object and then use the WeakReference to determine whether the object has been garbage collected.

You can also refer back to the original object referenced by the WeakReference using its Target property.

            Dog dog = new Dog("Bowser");

            WeakReference dogRef = new WeakReference(dog);

            Dog origDog = (Dog)dogRef.Target;

When you refer to the original object in this way, you add a reference to it, which means that it won’t get garbage collected.

            Dog dog = new Dog("Bowser");

            WeakReference dogRef = new WeakReference(dog);

            Dog origDog = (Dog)dogRef.Target;

            dog = null;
            GC.Collect();

            // Bowser still alive at this point, since we still have
            // a reference to him.

            Console.WriteLine(string.Format("Object still alive: {0}", dogRef.IsAlive));

734-001

#733 – How to Tell If an Object Has Been Garbage Collected

You normally can’t tell whether an object has been garbage collected by using some reference to the object–because once you have a reference to the object, it won’t be garbage collected.

You can instead create a weak reference to an object using the WeakReference object.  The weak reference is one that won’t be counted as a reference, for purposes of garbage collection.

In the code below, we check before and after garbage collection to show that a Dog object is garbage collected.

            Dog dog = new Dog("Bowser");

            WeakReference dogRef = new WeakReference(dog);
            Console.WriteLine(dogRef.IsAlive);

            dog = null;
            GC.Collect();

            Console.WriteLine(dogRef.IsAlive);

733-001

#732 – Destruction vs. Collection

Automatic memory management in C# means that the memory for a heap-based object is automatically released when there is no longer any user-written code that references the object.  This is done by the garbage collector.

An object goes through two distinct phases when it is no longer referenced–destruction and collection.

When an object is no longer referenced by any user-written code, other than code in a destructor, the object becomes eligible for destruction.

Once the object is eligible for destruction, it may be destructed at some point in the future, i.e. its destructor is called.

After the object is destructed and it is no longer being referenced by any code, including code in a destructor, the object becomes eligible for collection.

Once the object is eligible for collection, the garbage collector may at some point in the future release memory for the object.

#668 – GetTotalMemory Indicates How Much Memory You’ve Allocated

You can call the GC.GetTotalMemory function to find out the total # bytes you’ve allocated so far on the managed heap.  Note that this number does not include other memory that your process may have allocated, including things like memory allocated in unmanaged code.

        static void Main()
        {
            try
            {
#if DEBUG
                GC.Collect();
#endif
                Console.WriteLine(string.Format("Before we start, total mem alloc'd {0} bytes", GC.GetTotalMemory(false)));

                while (true)
                {
                    ConsoleKeyInfo cki = Console.ReadKey();

                    int size = 1024 * 1024 * 100;  // 100MB
                    byte[] data = new byte[size];

                    Array.Clear(data, 0, size);

                    _bigList.Add(data);

#if DEBUG
                    GC.Collect();
#endif
                    Console.WriteLine(string.Format("Total mem alloc'd now {0} bytes", GC.GetTotalMemory(false)));
                }
            }
            catch (Exception xx)
            {
                Console.WriteLine(xx.ToString());
                Console.ReadLine();
                }
        }

#427 – Finalizer Gotchas

The idea of the finalizer in .NET is that you can override the Object.Finalize method, called by the garbage collector when it’s releasing memory for an object, and you can do any required cleanup of unmanaged resources.

There are several things to keep in mind if you want to write a finalizer (done in C# using the destructor syntax):

  • You can’t predict when your finalizer is called
  • The finalizer might never get called at all
  • The order that finalizers are called in is unpredictable.  You therefore can’t assume that any other managed object that your object references still exists, or is in a known state.
  • Garbage collection will take longer if you have objects with finalizers

 

#424 – The Garbage Collector

In C#, you don’t explicitly delete heap-based objects.  Instead, the CLR will reclaim memory from objects that are no longer used, by running a Garbage Collector.

The garbage collector (GC) can release memory only for managed objects created on the heap.  It’s only job is to release memory.  It can’t clean up or release other resources, like file handles or database connections.

The GC will typically perform garbage collection when the amount of available physical memory is becoming too low or when the amount of virtual memory consumed by your application is becoming too large.

You can’t predict when garbage collection is going to happen, or even if it’s going to happen, prior to an application terminating.

#190 – Memory Management for Heap-Based Objects

In C#, you create an object on the heap when you instantiate an object using the new keyword.

            Person general = new Person("Julius", "Caesar");

We now have a Person object on the heap and a reference to that object–the variable general.

We can also declare a second variable that references the same object.

            Person antonysFriend = general;

Now we have one Person object on the heap and two references to it.

The memory for an object on the heap can be freed when it’s no longer being referenced by any variables.  This can happen when the variables that reference it go out of scope, or when they are set to point to another object.

More precisely, the memory will be reclaimed by the Garbage Collector (GC) in .NET.  When an application needs more memory, the GC is triggered and it releases memory for any dead objects.