How does garbage collection and scoping work in C#?

17,254

Solution 1

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.

Solution 2

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.

Solution 3

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.

Solution 4

  1. When an object no longer has a strong reference to it, nothing immediately happens. Each object is assigned a generation, 0, 1, or 2. Initially, all objects are placed in the 0 generation. Using the Mark-and-Sweep algorithm, the garbage collector will periodically check a generation. If the instance still has any strong references, it is promoted to a higher generation up to 2 (Which are usually checked less frequently). The theory behind this is that most objects are generally short lived, so if an object has lived long enough to make it to Generation 1, it doesn't need to be checked as often.
  2. There is no reference counting in the .NET GC. Rather it uses mark and sweep.
Share:
17,254
theheadofabroom
Author by

theheadofabroom

Updated on July 07, 2022

Comments

  • theheadofabroom
    theheadofabroom almost 2 years

    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

    1. "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?
    2. "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...

  • theheadofabroom
    theheadofabroom over 13 years
    Ok how about an example: I'm running through a loop, is there a way in which the first time I enter that loop I can instansiate a variable, then the next time round the loop that variable still has its old value until you change it, rather than being uninstansiated?
  • SLaks
    SLaks over 13 years
    @Bigg: Just move the variable outside the loop.
  • theheadofabroom
    theheadofabroom over 13 years
    I'm not asking for a workaround, I'm asking what the behaviour is/should be. I would hope the answer was no, and this is a crude example to try and illustrate my thinking.
  • SLaks
    SLaks over 13 years
    Without moving the variable, no. That variable is scoped to the loop's inner block; after that iteration it's gone (unless preverved elsewhere, such as a lambda)