Garbage Collection (1), Manage Managed Code

This article describes the core concepts of garbage collection: the process of the memory management of .NET for managed code,. The part (2) of this article will discuss how to manage the unmanaged code in .NET, the Dispose Pattern.


Managed code is the code which is managed by the CLR (Common Language Runtime) in .NET Framework, whereas the Unmanaged code is the code which is directly executed by the operating system.
Unlike in C++ where both the memory allocation and release are manually handled by developers, in the common language runtime (CLR), the garbage collector (GC) serves as an automatic memory manager, doing the same job.
For developers working with managed code, this means that you don't have to write code to perform memory management tasks. Automatic memory management can eliminate common problems, such as forgetting to free an object and causing a memory leak or attempting to access memory for an object that's already been freed.

Summary of Memory Management and Garbage Collection

Garbage Collection: The automatic memory management scheme by the .NET, i.e., a background mechanism to clean up unreferenced heap memory.
  • When allocating memory for a new object on the heap without sufficient free memory, the .NET Framework starts the garbage collection process:
    • visiting all the objects in the heap and marks those objects pointed to by any variable.
    • releasing the unmarked objects (not unreachable by any variables).
  • The process is nondeterministic.
  • It can be enforced by GC.Collect(), at Dispose()
  • The system has low physical memory.
  • The memory that is used by allocated objects on the managed heap surpasses an acceptable threshold. This threshold is continuously adjusted as the process runs.
  • The GC.Collect method is called.

Figure 1. Simplified model of the managed heap (this is not what is actually implemented.)
The rules for this simplified model,
  • All garbage-collectible objects are allocated from one contiguous range of address space.
  • The heap is divided into generations so that it is possible to eliminate most of the garbage by looking at only a small fraction of the heap.
  • Objects within a generation are all roughly the same age.
  • Higher-numbered generations indicate areas of the heap with older objects—those objects are much more likely to be stable.
  • The oldest objects are at the lowest addresses, while new objects are created at increasing addresses. (Addresses are increasing going down in Figure 1 above.)
  • The allocation pointer for new objects marks the boundary between the used (allocated) and unused (free) areas of memory.
  • Periodically the heap is compacted by removing dead objects and sliding the live objects up toward the low-address end of the heap. This expands the unused area at the bottom of the diagram in which new objects are created.
  • The order of objects in memory remains the order in which they were created.
  • There are never any gaps between objects in the heap.
  • Only some of the free space is committed. When necessary, more memory is acquired from the operating system in the reserved address range.

Collecting the Garbage

The easiest kind of collection to understand is the fully compacting garbage collection, this graph will demostrate the process:
Figure 2. Illustrated garbage collection process.


This article describes the core concepts of garbage collection, the part (2) of this article will discuss How to manage the unmanaged code in .NET, the Dispose Pattern.