Click here to Skip to main content
13,259,539 members (64,286 online)
Click here to Skip to main content
Add your own
alternative version


22 bookmarked
Posted 2 Mar 2004

Controlling object life time and garbage collection in .NET

, 2 Mar 2004
Rate this:
Please Sign up or sign in to vote.
This article discusses scenarios where we have to take care of an object's life time and cannot rely on JIT's marking of objects for garbage collection.


Managed applications and garbage collection advertise that the developer need not care about memory allocations and object lifetime, leaving them to the mercy of Garbage Collector. The JIT compiler has a mind of its own and optimizes the code under the hood. This veils the developer from the object's moment of abrogation. Although we do not know the moment of an object's destruction, careful planning and design are required to orchestrate with the Garbage Collector to avoid pitfalls.

The Problem

Guessing when and where the object is marked for garbage collection is tricky. Consider the following code :

namespace NS
    class A
        public static void Main()
            System.String s;
            s = "some test string"; 
            // <- is s marked for collection after this ?
            System.Int32 i;
            i = 10;
        }    // <- is s marked for collection here ? 

The place where string s is marked for garbage collection by JIT is not known exactly. This is especially a problem when we try to control objects which are required throughout the life of an application.

Sample solution

A common example that is quoted is a mutex which is used to make sure that only one instance of the application is running. The following code illustrates this:

namespace NS
    class SomeFormClass:System.Windows.Forms.Form
        public static void Main()
            bool created;
            System.Threading.Mutex m = new 
                System.Threading.Mutex(true, "OnlyOneApp", out created);
            if (! created)
            // <- mutex may be marked for garbage collection here ! 
            // if the application runs for long and mutex
            // is garbage collected, the design fails
            System.Windows.Forms.Application.Run(new SomeFormClass()); 
            // <- this will keep the mutex alive till this point 

If the GC.KeepAlive() statement is missing, the JIT compiler might optimize and mark the mutex for garbage collection before the Application.Run() statement. The GC.KeepAlive() statement keeps the object alive upto that statement. In the above scenario, we know the exact place where the mutex is created and till where it is required. Another point is that the variable is accessible at both these known points. Consider an example where an object is required throughout the application but its instantiation point is unknown. Also, it is assumed that no single "live" object may be holding a reference to this required object throughout the life of the application. This scenario prompts the JIT to mark the object for garbage collection at the earliest point where the object goes out of scope. The code below illustrates a design to keep this kind of objects alive and also points out how to handle the situation in Console and Windows applications. It is most important to use the GC.SuppressFinalize() method at the end when the application exists, otherwise the application will go into an infinite loop and hangs.

namespace GCDemo
    // class used to test the scenario
    class StartTest
        // following delegate and event are required by console apps
        // In Windows apps, this will be taken care by ApplicationExit event
        internal delegate void ApplicationExit();
        static internal event ApplicationExit AppExit;
        public static void Main()
            for (int i=0; i<3; i++)
                new GCDemo(); // <- creating 3 objects here as a test case
            // <- we expect the JIT to mark for
            // garbage collect these objects atleast here
            // following lines are required for a console app,
            // Application.ApplicationExit event is raised by windows apps
            if (AppExit != null) 
    // this class object should be kept alive for the entire application life
    public class GCDemo
        public GCDemo()
            // register with the application exit event
            // AppExit is my own event for console applications
            // See the declaration in StartTest class above
            StartTest.AppExit += new StartTest.ApplicationExit(AppExiting);

            // for windows app use the line below by 
            // implementing a EventHandler delegate
            // Application.ApplicationExit += new EventHandler(eventhandler);

            // ReRegisterForFinalize will put the entry back in the queue
            // and resurrect the object 
        void AppExiting()
            // suppressing the finalization will
            // stop the application from hanging 

Sometimes, it is worth calling GC.Collect() and GC.WaitForPendingFinalizers() like shown below before allocating huge memory, especially when there is a crunch on memory.

for (int i=0; i<1000; i++)
        somelist.Add(new someobject());


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Sriram Chitturi
United States United States
No Biography provided

You may also be interested in...


Comments and Discussions

GeneralYipes! Don't rely on finalization Pin
Anthony Berglas16-Mar-04 16:03
memberAnthony Berglas16-Mar-04 16:03 
GeneralRe: Yipes! Don't rely on finalization Pin
Nathan Holt at CCEI22-Mar-04 7:04
memberNathan Holt at CCEI22-Mar-04 7:04 
GeneralLisp/Java/.Net is NOT C++ Pin
Anthony Berglas22-Mar-04 13:18
memberAnthony Berglas22-Mar-04 13:18 
GeneralRe: Lisp/Java/.Net is NOT C++ Pin
gnk26-Jun-07 17:12
membergnk26-Jun-07 17:12 
GeneralPoint noted Pin
Sriram Chitturi10-Mar-04 7:13
memberSriram Chitturi10-Mar-04 7:13 
GeneralYes, I mostly agree with zucchini. Pin
Keith Vinson10-Mar-04 6:13
sussKeith Vinson10-Mar-04 6:13 
GeneralRe: Yes, I mostly agree with zucchini. Pin
Sriram Chitturi11-Mar-04 4:17
memberSriram Chitturi11-Mar-04 4:17 
GeneralRe: Yes, I mostly agree with zucchini. Pin
Keith Vinson11-Mar-04 6:44
memberKeith Vinson11-Mar-04 6:44 
GeneralRe: Yes, I mostly agree with zucchini. Pin
zucchini11-Mar-04 5:22
memberzucchini11-Mar-04 5:22 
GeneralRe: Yes, I mostly agree with zucchini. Pin
Keith Vinson11-Mar-04 6:31
sussKeith Vinson11-Mar-04 6:31 
Yes, In the case you created, an optimizing compiler could / should id the array as never being used after the for loop. That is because the object in question is truly local.

However, in the case of the mutex cited in the article. The object is a global, system wide entity. It would be interesting to know if compiler / GC is smart enough to figure this all out. I doubt it.

I think the GC works on scope boundaries not extant of references. I would be willing to bet that the reference counting that keeps an object alive is triggered by pushing and popping object references onto the stack frame. AKA {}(bracket preamble/post amble routines), as well as other types of assignment operations. Check the disassembly code window, does anyone see any ref counting code interspersed with your code???

I doubt an optimizing compiler would bother to call a object --reference count routine as soon as it could while not executing the code it was suppose to be executing Smile | :)

As a final thought does the GC even have a thread other that your default thread to run on unless you call it? I know there are framework threads hanging around but does the GC have access to them? I bet it doesn't. That would explain why the GC doesn't do clean up unless its forced to, and one application doesn't seem to be able to trigger a GC cycle in another application.

As a real world example: a NT service used to transfer files to/from other computers. Runs 24 x 7, after about a week the machine begins to drag ass. Almost all of its VM is taken up by the .NET system service. Add a few well placed calls to GC.Collect and all is well in la la land...

I guess its more fun to pontificate, than to test...

GeneralRe: Yes, I mostly agree with zucchini. Pin
Sriram Chitturi13-Mar-04 5:10
memberSriram Chitturi13-Mar-04 5:10 
QuestionI'm skeptical about the last example; have you tested this? Pin
zucchini10-Mar-04 4:50
memberzucchini10-Mar-04 4:50 
AnswerRe: I'm skeptical about the last example; have you tested this? Pin
Sriram Chitturi11-Mar-04 4:34
memberSriram Chitturi11-Mar-04 4:34 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web04 | 2.8.171114.1 | Last Updated 3 Mar 2004
Article Copyright 2004 by Sriram Chitturi
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid