Running Finalizers
When you free an object, you often need to do some cleanup. In an environment with manual memory management, this cleanup happens in a destructor, which is also responsible for destroying (references to) other objects.
In a garbage-collected environment, you only need to clean up things that aren't managed by the collector itself, which simplifies matters slightly. Garbage-collected languages provide the idea of a finalizersome code that's used to release manually managed resources when an object is destroyed.
One of the advantages of garbage collection is the ability to do this cleanup in another thread. In Objective-C, finalizers and memory reclamation all happen in a background thread when running in garbage-collected mode. Contrary to what you might expect, this design can improve responsiveness. When you free an object with manual memory management or reference counting, you typically do all of this work in your thread. If you delete an object in C++, then you call its destructor, which calls the destructors of everything it owns, and so on. If this is something like the DOM tree for a web page, then it can take a noticeable amount of time to walk the entire structure and free everything. In contrast, a garbage-collected language will do the same work in a background thread, saving you this interruption.
It's often said that garbage collection is incompatible with real-time applications. In fact, any memory allocation is. For example, there's a reason why the Symbian nanokernel doesn't permit memory allocation: It's required to make hard real-time guarantees. Walking a heap to allocate or free a block of memory isn't deterministic. This is even more important in the presence of swapping. The delay from having to swap a page of memory back from disk can be anywhere from about 5 ms. upwardsfar more than the latency than garbage collection would introduce.