Garbage collector is a memory manager that's part of the Common Language Runtime (CLR), which lies at the heart of Microsoft's .NET Framework.
CLR manages lots of different jobs such as code access security, type safety, compiling code to Microsoft Intermediate Language (MSIL), Just in Time (JIT) compilation to compile MSIL to native code, as well as providing memory management and a runtime environment in which to run the programs.
CLR uses Garbage Collector to automatically manage memory usage. Garbage Collector has removed the requirement on developers to manage memory explicitly. It runs in the background during an application, preventing common memory leaks by freeing up memory from objects, once the application has finished using them.
.NET's Garbage Collector has made memory management considerably easier, but it doesn't eliminate the need to track and manage system resources. Here are a couple of its limitations:
Memory Leaks Due to Unused Objects that are Still Referenced
Generally, we assume that the Garbage Collector detects and removes unused objects. Actually, it finds only unreferenced objects. If a program never refers to an object again, but there is some path leading to that object then the Garbage Collector does not release its memory. These objects are known as unused objects and lead to memory leaks.
In .NET, memory leaks occur when an object has a reference but the program never uses it. It is very hard to detect the source of these memory leaks, although symptoms of rising memory usage are obvious. A memory profiler is essential for determining the unused objects and tracing the references to find out why Garbage Collector is not collecting the object.
Fragmentation of the Heap
Another very well known limitation of .NET is its large object heap. If an object becomes part of this heap, the runtime does not move it. This can lead to a program running out of memory prematurely. When Garbage Collector collects a large object from this large object heap, it can also leave behind holes in the heap, thereby causing the free space to become fragmented. The problem occurs a large block of memory is required, but the heap has become so fragmented that there is no single region of memory big enough to accommodate it.