Re: to dispose or not ?
- From: "Michael D. Ober" <obermd.@.alum.mit.edu.nospam.>
- Date: Sun, 2 Aug 2009 14:50:35 -0600
The dotNet garbage collector is, at it's heart, a move to another heap style collector for the Gen0 and Gen1 heaps and a mark/sweep/compact collector for the Gen2 heap. What this means is that the runtime keeps a list of all known starting points for the heaps and either moves the objects to the next heap or compacts free space out of the heap (Gen2 only). Known starting points include, but are not limited to, global variables and the stack frames for each thread. There are NO reference counters in the garbage collector's managed memory. Setting an object to Nothing simply releases the reference from the variable to the object in the heap. The problem is that neither the VB nor the C# (obj = null;) compilers is smart enough to realize that this statement should simply be ignored and not generate code.
Since I didn't see the entire thread, I'm making an assumption that you are coming from a VB6 background and that you are using the VS debugger and seeing that the objects are still accessible after you are done with them. In debug mode, the compiler internally sets a GC.KeepAlive at the end of each method (function, sub, property) on all objects created in the current method that are not returned by the function or property get or attached to another object. I'm not sure the exact mechanism for this, but the end result is that objects in debug releases are kept to the end of the method even if they are no longer referenced, allowing you to inspect their contents anywhere in the method. In release code, this doesn't happen and the GC may safely collect these objects in the middle of a method.
As for the code being "too complicated" for the GC to figure out, that simply cannot happen given that at any time during the execution of a program, you can always identify memory that is accessible given that you always have the system memory roots available. If an object isn't accessible from a root, your code can no longer see it. Note that this is only true for 100% managed code. As soon as you start calling COM objects and DLLs outside the managed environment, you need to use the interop libraries and sometimes the GC.KeepAlive methods to give the garbage collector the information it needs to avoid collecting memory used to pass data between the COM and DLL objects and the managed code. The interop and GC.KeepAlive calls provide a method for the programmer to tell the GC that specific objects are a known "root" for garbage collection purposes.
Mike Ober.
"Stewart Berman" <saberman@xxxxxxxxxxxxx> wrote in message news:meob75lbon3d34qkl2jas781npqt5enbe9@xxxxxxxxxx
Wouldn't setting the object to nothing serve the same purpose as calling the KeepAlive method? It
is a marker for the last place in code that the object is needed. Furthermore, if, by some chance,
the code is too complicated for the GC to figure out that the object is no longer needed at that
point, setting the reference to nothing reduces the reference count to zero and lets the GC know
that the object can be collected early.
Isn't:
obj = nothing
Clearer than:
GC.KeepAlive(obj)
To indicate that obj is no longer needed?
I am also somewhat confused by the example. It does not appear that the console control handler is
removed anywhere in the code. So if it is collected after the GC.KeepAlive(hr) call wouldn't the
Console.Read() cause a problem if the user responded with Ctrl-C?
"Scott M." <s-mar@xxxxxxxxxxxxx> wrote:
It seems that my original assertion that setting an object reference to
Nothing will, in fact, potentially delay the object's removal from the heap
if the GC collects during a method where the object was instantiated, but
not used anymore, at the point that the GC collects, is correct.
TheGC has a KeepAlive method MSDN explains:
"The purpose of the KeepAlive method is to ensure the existence of a
reference to an object that is at risk of being prematurely reclaimed by the
garbage collector. A common scenario where this might happen is when there
are no references to the object in managed code or data, but the object is
still in use in unmanaged code such as Win32 APIs, unmanaged DLLs, or
methods using COM.
This method references the obj parameter, making that object ineligible for
garbage collection from the start of the routine to the point, in execution
order, where this method is called. Code this method at the end, not the
beginning, of the range of instructions where obj must be available.
The KeepAlive method performs no operation and produces no side effects
other than extending the lifetime of the object passed in as a parameter."
ms-help://MS.VSCC.v90/MS.MSDNQTR.v90.en/fxref_mscorlib/html/2e1bb318-c0dc-11f7-875f-6d25db308dab.htm
-Scott
"Tom Shelton" <tom_shelton@xxxxxxxxxxxxxxxxxx> wrote in message
news:OkjYiixCKHA.3732@xxxxxxxxxxxxxxxxxxxxxxx
On 2009-07-22, Scott M. <s-mar@xxxxxxxxxxxxx> wrote:
Yes, I call Close if it is available, Dispose if it is available and
then
set the object to nothing
before it goes out of scope.
Why do you set the object to Nothing? This doesn't buy you anything and,
in
fact, can actually delay cleanup of your object, rather than hasten it.
Actually, not any more - the compiler can detect this and actually
optimizes
it away (at least in release mode).
As I see it, the only open item is whether or not to force garbage
collection.
I don't think that's an open issue at all. I think it's pretty well
established (and benchmarked) that in all but the most rarest of
occassions,
this will degrade application performance and is not recommended.
Yep.
--
Tom Shelton
.
- Follow-Ups:
- Re: to dispose or not ?
- From: Stewart Berman
- Re: to dispose or not ?
- References:
- Re: to dispose or not ?
- From: Scott M.
- Re: to dispose or not ?
- From: Stewart Berman
- Re: to dispose or not ?
- Prev by Date: Re: to dispose or not ?
- Next by Date: Re: to dispose or not ?
- Previous by thread: Re: to dispose or not ?
- Next by thread: Re: to dispose or not ?
- Index(es):
Relevant Pages
|