Great question! (I thought I would find a hoax, but no, strange, such an important aspect in C that seems to have never been asked before)
There are two questions that I found for some of this field:
They are mainly focused on the goto path. So first allow it.
Goto method
If you have code that depends on the allocation of several resources that are subsequently to be released, you can use the template as shown below:
int function(void){ res_type_1 *resource1; res_type_2 *resource2; resource1 = allocate_res_type_1(); if (resource1 == NULL){ goto fail1; } resource2 = allocate_res_type_2(); if (resource2 == NULL){ goto fail2; } return SUCCESS; fail3: free_res_type_2(resource2); fail2: free_res_type_1(resource1); fail1: return FAIL; }
You can read more about this approach in the excellent Regehr blog: http://blog.regehr.org/archives/894 , also pointing to the Linux kernel, which often uses this template.
Arrow code
This is one possible way to do it differently. The above example looks like this: arrow:
int function(void){ res_type_1 *resource1; res_type_2 *resource2; int ret = FAIL; resource1 = allocate_res_type_1(); if (resource1 != NULL){ resource2 = allocate_res_type_2(); if (resource2 != NULL){ free_res_type_2(resource2); } free_res_type_1(resource1); } return ret; }
The obvious problem that the template got its name with is the potentially deep embedding (code similar to an arrow), why this template is so disliked.
other methods
I canβt think about the need to allocate and free resources (with the exception of the flag option that you describe in detail in your question). You have more freedom, if you do not have such a restriction, you can see some good approaches described in other questions and answers.
If the resources are independent of each other, you can also use other templates (for example, the early return that your first code example provides), however these two are the ones that can work correctly with the resources if you need it (i.e. resource2 can be assigned only on top of a valid resource1), and if the free function of this resource does not handle an unsuccessful return return.