In principle you could install a handler with atexit
that knows how to free your buffers. The handler will be called as a consequence of func1
calling exit
. It's not very pleasant to use -- the handler takes no parameters, which means you need to use globals (or local static variables) to store the thing that needs to be freed. It can't be unregistered, which means you need to set those globals to null (or some other special value) to indicate that you've freed the resources yourself, but the handler will still be called. Normally you'd use the atexit
handler as the "hook" from which to hang your own resource cleanup framework.
In practice, that's usually too much hassle for a few malloc
ed buffers, because when the program exits a full-featured OS will in any case release all memory reserved by the process.
It can even be costly to free memory before exit - in order to free each allocation with free
, the memory will be touched, which means it needs to be dragged into cache from main memory or even from swap. For a large number of small allocations that might take a while. When the OS does it for you, it just unmaps the memory map for the process and starts re-using that address space / memory / swap space for other things in future. There are benefits to cleaning up (for example, it makes your code easier to re-use and it makes real leaks easier to find), but also costs.
By the way, it's rather anti-social of the function func1
to call exit
on error, because as you've discovered it places limits on users of the function. They can't recover even if they think their program can/should carry on despite func1
failing. func1
has in effect declared that it is too important for the program to even dream of continuing without its results. Yes, GMP, I do mean you.