This question already has an answer here:
- Understanding garbage collection in .NET 3 answers
I'm learning C# coming from python and wish to know how the C# garbage collector works - I found that I understood a lot more about python once I figured out what it was doing behind the scenes, and wish to avoid making the sort of noob errors I made at first when learning python.
I've not been able to find any good clear explanations of when an item is garbage collected and am left with questions such as
- "What happens to an object when its last reference passes out of scope?" Does that object get garbage collected or is it still there when you pass back into the scope in which it was defined?
- "At what point is the number of refernces decremented?" Leading me to wonder whether it even uses reference counting or some other technique...
Answers to these, or even better a clear consise overview of what's actually going on will win cookies (or upvotes), and even better if your answer compares it to the python way of doing things. I'm not interested in which is better, just the details. Also answers on my original post on programmers.stackexchange would be much appreciated...
The dotnet GC engine is a mark-and-sweep engine rather than a reference-counter engine like you're used to in python. The system doesn't maintain a count of references to a variable, but rather runs a "collection" when it needs to reclaim RAM, marking all of the currently-reachable pointers, and removing all the pointers that aren't reachable (and therefore are out of scope).
You can find out more about how it works here:
http://msdn.microsoft.com/en-us/library/ee787088.aspx
The system finds "reachable" objects by starting at specific "root" locations, like global objects and objects on the stack, and traces all objects referenced by those, and all the objects referenced by those, etc., until it's built a complete tree. This is faster than it sounds.
Garbage collection is not triggered by references going out of scope. Garbage collection is usually triggered when allocating storage for new objects - specifically when generation zero's budget is exhausted. I.e. there may be a significant delay between when objects are eligible for garbage collection and when they are actually collected. As others have already pointed out, the CLR doesn't use reference counting. Instead it employs a mark and sweep approach.
A good source of information on all the details about how garbage collection works is Jeffrey Ricther's book CLR via C#. The book goes into great detail about how the heap is partitioned and how garbage collection works. Highly recommended if you're interested in .NET implementation details.
'Garbage Collection' is performed by Garbage collector which is a part of CLR in .NET framework.
Its a automatic process of freeing up memory by identifying objects that are no longer required unlike c, c++ where programmer explicitly had to deallocate memory.
How garbage collector works
It periodically looks in memory i.e managed heap and frees up memory occupied by dead-objects.
dead-object is identified if it is unreachable by your code.
Implementation
There are 3 ways in which you can implement memory management:-
GC works only for managed resources, therefore .NET provide Dispose and Finalize to release unmanaged resources like stream, database connection, COM objects etc..
1) Dispose
Dispose must be called explicitly for types which implements IDisposable.
Programmer must call this either using Dispose() or via Using construct
Use GC.SuppressFinalize(this) to prevent call to Finalizer if you have already used dispose()
2) Finalize or Distructor
It is called implicitly after object is eligible for cleanup, finalizer for objects are called sequentially by finalizer thread.
Drawback of implementing finalizer is that it memory reclaim gets delayed as finalizer for such class/types must be called prior cleanup, so an additional colect to reclaim memory.
3) GC.Collect()
Using GC.Collect() doesn't necessarily put GC for collection, GC can still override and run whenever it wants to.
also GC.Collect() will only run the tracing portion of garbage collection and add items to finalizer queue but not call finalizers for the types, that is handled by another thread.
Use WaitForPendingFinalizers if you want to make sure all finalizers have been callled after you invoke GC.Collect()
Refer to post on my blog where i have this article :- Garbage collection in .NET
At some indeterminate point in time after the last reference to an object disappears, the object will be collected.
The second part of your first question doesn't make sense.
If you can get back into the scope in which an object was defined (eg, a lambda expression), there is obviously still a reference.
The GC does not use reference counting at all.
Rather, it uses a mark-and-sweep algorithm.