Many functions require the allocation of multiple objects. Failing and returning somewhere in the middle of this function without freeing all of the allocated memory could produce a memory leak. It is a common error to forget to free one (or all) of the objects in this manner, so a goto-chain is the simplest and cleanest way to organize exits when order is preserved.
Noncompliant Code Example
int do_something(void){ // ... definitions ... obj1 = malloc(...); if (!obj1){ return -1; } obj2 = malloc(...); if (!obj2){ free(obj1); return -1; } obj3 = malloc(...); if (!obj3){ free(obj2); return -1; // Forgot to free obj1 -- Memory leak } // ... more code ... }
Notice how there is a memory leak if obj3 cannot be allocated. This is also just a small example; in much larger examples, errors like this would be even harder to detect. Hence, the goto-chain...
Compliant Solution
int do_something(void){ // ... definitions ,,, obj1 = malloc(...); if (!obj1){ goto FAIL_OBJ1; } obj2 = malloc(...); if (!obj2){ goto FAIL_OBJ2; } obj3 = malloc(...); if (!obj3){ goto FAIL_OBJ3; } ? // ... more code ... FAIL_OBJ3: free(obj2); FAIL_OBJ2: free(obj1); FAIL_OBJ1: return -1; }
This code is guaranteed to clean up properly whenever an allocation fails. It is cleaner and prevents rewriting of similar code upon every function error.