To prevent a process from crashing due to a System.OutOfMemory condition, the .NET garbage collector (GC) automatically defragments virtual memory. It can only do this for Gen 0 and Gen 1 memory allocations. Any allocations at 64 KB or larger will go to the large object heap. The large object heap and any non-managed objects (COM, C++, etc.) cannot be defragmented by the GC.
I recently published an article on the Microsoft Technet Wiki PerfGuide on diagnosing process virtual memory issues.
PerfGuide: Out of Process Virtual Memory
In any case, PAL is looking for a gradual and significant increase in process committed memory for which the operating system must provide system committed resources (physical RAM and/or page file). The committed memory of each process can be measured using the “\Process(*)\Private Bytes” counter. The amount of committed memory of a process is dictated by the process’s usage of memory – coded by the developer of the application. The .NET GC also removes/deallocates variables that are out of scope (such as local variables in a function that is no longer executing), but ultimately, the application developer determines which variables are in use. Therefore, we diagnose the memory usage of the application threw debugging or profiling to determine where the memory usage goes. My point is that, yes, you can have a memory leak even if you are using pure .NET. The GC just makes it less likely to happen.
With all of that said, memory leaks need to be looked at over a long period of time because when an application is busy, it will naturally use more memory. A memory leak is when the memory accumulates unnecessarily.
If a process has plenty of virtual memory (x64 has 8 TB of virtual memory per process) and if the leak continues unchecked, then the system might eventually run out of system commit memory which is the total amount of RAM and all of the page files combined. For more information on this topic, see the following PerfGuide post.
PerfGuide: Out of System Committed Memory
We [Microsoft] typically work with applications in production, so we commonly use DebugDiag or WinDBG to analyze memory leaks by gathering several dumps (*.dmp) from the target process.