Re: to dispose or not ?

Tech-Archive recommends: Repair Windows Errors & Optimize Windows Performance



"Stewart Berman" <saberman@xxxxxxxxxxxxx> wrote in message news:ouud755acls1n9k8g60du34hvsduu94sfd@xxxxxxxxxx
>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

It appears that relatively simple completely managed code is too confusing for the GC to figure out
and requires a GC.KeepAlive to tell it what to do:
http://support.microsoft.com/kb/821779

I wasn't aware of this behavior, but it make sense given that the finalizers are run in indeterminate order. It also means that MS took some shortcuts in the garbage collector to improve the performance of finalizers. I pasted the VB version of this code into a new console project and verified this behavior in VS 2008 (framework 2.0). I also tested the behavior with "test = Nothing" instead of the GC.KeepAlive(test) statement. Setting the variable to Nothing doesn't prevent the exception from being generated.



"Michael D. Ober" <obermd.@.alum.mit.edu.nospam.> wrote:

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








.



Relevant Pages

  • Re: to dispose or not ?
    ... always have the system memory roots available. ... collector for the Gen0 and Gen1 heaps and a mark/sweep/compact collector for ... heap or compacts free space out of the heap. ... the reference from the variable to the object in the heap. ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Could you please give me some advice on GC in C?
    ... memory alloc/free. ... Reference counting is probably the simplest way to gc library- ... 2-space copying collector on top of malloc and free. ...
    (comp.lang.c)
  • Re: Form not disposing due to lingering reference
    ... But I'm not sure you fully understand memory management in .NET. ... Not that it necessarily matters here, but it's not the only reference that exists. ... And assuming the instance is no longer reachable from _any_ data structure, yes...the collector has the possibility to collect that memory. ... a ToolStrip with some ToolStripButtons and a TabControl ...
    (microsoft.public.dotnet.framework)
  • Re: Memory leaks in managed code?
    ... Is the only goal consolidation of free space? ... it makes sense to free up block by consolidating memory. ... when two objects have a reference to eachother. ... workings on the CLR garbage collector? ...
    (microsoft.public.dotnet.languages.csharp)
  • Re: Looping-related Memory Leak
    ... memory leak / balloon for reasons I cannot figure out. ... end of the loop. ... reference count never reaches zero, and they remain alive until the ... the generational collector doesn't break cycles that involve ...
    (comp.lang.python)