initialize all resource pointers to NULL;
attempt all allocations;
if all pointers are non-NULL, do the thing (typically calling another routine)
free all non-NULL pointers
realloc(ptr, 0) nicely handles allocations and possible-NULL deallocations
if you must have a `free_on_exit()`
(for example, if you allocate a variable number of pointers in a loop)
then build your own defer stack registering pointers using memory that you allocate
simply checking for NULL doesn't allow that - for example for something that might have been opened with fopen() needs to be closed with fclose() rather than free(), and you can't tell that from the pointer.
I think the implication was that they're pointers to objects that own resources (like containing FILE handles) and need to be "freed" with a custom function, not just "free".
the way i do this in C looks like
realloc(ptr, 0) nicely handles allocations and possible-NULL deallocations