In the style of memory management typically used in C, the information which tracks which areas of the heap are free or allocated is separate from the information which indicates what areas are actually used. When information on the heap is no longer needed, code must explicitly mark it as unallocated or else it may remain allocated forever.
A garbage-collection-based system regards all the heap-object references in the system as the definitive indicator for which objects are used. Because it would be impractical to scan all the object references in the system every time an object was allocated, the system effectively "batches" the work: as long as free memory space still exists on the heap, memory is simply allocated to objects sequentially. No attempt is made to reclaim any space until the heap gets too full.
An object will be considered to be "used" if any thread holds a reference to it in a local variable, or if any global variable holds a reference to it, or if object which is considered "used" holds a reference to it in any field. The compiler can usually tell if a local variable that holds a reference to an object will never actually be used, but it cannot make such determinations with global variables or object fields. If an object which is going to be useful holds an object reference which is never again actually going to be used, that reference should be set to null (Nothing in VB). If this is not done, the useless object will be "kept alive" as long as the useful object is. If the useful object is something like an application's main form, the result may be a memory leak that persists as long as the application remains open.