It has a development-related side, too. Freeing everything correctly in
the end
- increases understanding of inter-object ownerships,
- helps debugging with valgrind or one's custom allocator,
- makes it easier to embed the program into another program (or
library).
Perhaps such a final cleanup should depend on a compile time (or
runtime) toggle.
It is not easy to spot a leak if everything is leaked in case of a
successful exit. If suddenly the program must do the same thing in a
loop, leaking becomes an issue.
Most runtime allocator libraries have some kind of "shutdown" call
which can indicate that the process is cleanly terminating and that
all allocations should be considered freed following the call. For
release builds, shutdown typically does nothing or, at worst, it
simply resets the allocator's internal data structures. For debug
purposes, most allocators have the ability to provide a list of
unfreed blocks.
However, in many cases, runtime debugging behavior is configurable and
all or part of the debugging API is hidden. Many compiler vendors
document their debug APIs only for internal use or in SDKs intended
for use by supplementary tool vendors ... thus ordinary programmers
rarely see it.
George