The obvious cases for not using garbage collection are hard realtime, severely limited memory, and wanting to do bit twiddling with pointers. Are there any other, less discussed, good reasons why someone would prefer manual memory management instead of GC?
Emm... my professor's reason is to make our (his students') life harder and to teach us "the real thing". Haha :)
In general, though, garbage collection is not always optimized for your specific app, so if you're one good programmer, you will definitely do a better job at memory management than GC ever will.
Temporary insanity?
Actually the only case I know of that you haven't covered is so-called "lifetime-based memory management", which sometimes goes under the name "pools" or "arenas" or "regions". The idea is that you're going to allocate a ton of objects, probably small, and they're all going to die at once. So you have a cheap allocator and then you recover all the objects in a single free operation.
These days there are program analyses that will enable a compiler to do this for you, but if you're writing C code, you do it by hand. There's an implementation with examples in Dave Hanson's C Interfaces and Implementations, and it's used in Fraser and Hanson's lcc
compiler, which is written in C without a garbage collector.
When programming for embedded devices with limited resources. iPhone, for instance, uses reference-counting.
Or when programming something that is extremely intensive on your computer. SETI@Home and video games come to mind.
I would advise that you don't manage your own memory unless the situation dictates it's really necessary. Somebody famous once said that code is twice as hard to debug as it is to write. Well, memory management is hard enough in the first place. :)
When you are building high-performance apps such as first person shooter games, you don't want GC that will potentially impact your app's execution. Manually managing the memories in those apps allow you to decide the right time to free up resources.
The only reason NOT to use Garbage Collection for resource management is if you want to use RAII ala C++, but as it applies purely to memory, even then it's a reasonable idea to use it. (Note: It's still possible to do so, with gotcha's related to non-deterministic finalization).
That said, using Garbage Collection can use more memory than is strictly needed, so in severely memory constrained areas where one can not even spare the memory for managing the GC routines (and the code), then that's a good reason not to use it, too.
Additionally, if the language you use doesn't contain GC by default, such as C++, and you like to use RAII, then that's a reasonable reason too, though for some problems it can be very useful.
Ultimately it comes to tradeoffs - the more specialized your requirements, especially with regards to thread-safe RAII, the more complex it is to implement the GC, and GC might not buy you very much for your application.
If you have a ton of objects which are freed rarely the garbage collector will start and waste time just to find out that there are only a few objects to finalize. In extreme cases this may cause a huge performance penalty.
If you had infinite memory you'd not need garbage collection. :)
How about for security reasons? Eg if you've got an encryption private key in memory, you'd probably want it around for the shortest possible time.
Having said that, i think the way hardware is heading, learning the art of multithreaded programming may be more worth learning.
It IS possible to use garbage collection with hard real time, if you have fully incremental garbage collector with bounded execution time per byte of allocated memory, so, crazily enough, it is NOT necessarily a reason not to use garbage collection :)
One fundamental problem with garbage collection, though, is that it is difficult to estimate and manage the actual size of the working set in memory, because garbage collector can free your memory only delayedly. So, yes, when memory is restricted, garbage collection might not be a good choice.
Another problem with garbage collection is that it sometimes interferes with freeing other resources such as file descriptors, window handles, etc., because, again, the garbage collector might free those resources only delayedly, causing resource starvation.
Garbage collection can also cause cache trashing, because the memory is not necessarily allocated in a local fashion. For example, stack allocated memory is much more cache-friendly than heap-allocated short-lived objects.
Finally, garbage collection of course consumes CPU time :) So if you can code manually memory management you can save the CPU cycles the garbage collector would consume :)