4 ms·
What is the recommended way to use defer to free values only on an error path (rather than all paths)? Currently I use goto for this: void* p1 = malloc(...
by zyedidia 2y ago
What is the recommended way to use defer to free values only on an error path (rather than all paths)? Currently I use goto for this:
void* p1 = malloc(...);
if (!p1) goto err1;
void* p2 = malloc(...);
if (!p2) goto err2;
void* p3 = malloc(...);
if (!p3) goto err3;
return {p1, p2, p3};
err3: free(p2);
err2: free(p1);
err1: return NULL;
With defer I think I would have to use a "success" boolean like this:
bool success = false;
void* p1 = malloc(...);
if (!p1) return NULL;
defer { if (!success) free(p1) }
void* p2 = malloc(...);
if (!p2) return NULL;
defer { if (!success) free(p2) }
void* p3 = malloc(...);
if (!p3) return NULL;
defer { if (!success) free(p3) }
success = true;
return {p1, p2, p3};
I'm not sure if this has really improved things. I do see the use-case for locks and functions that allocate/free together though.
- lelanthran 2y agoI don't even bother with `error1`, `error2`, ... `errorN`. I initialise all pointers to NULL at the top of the function and use `goto cleanup`, which cleans up everything that is not being returned ... because `free(some_ptr)` where `some_ptr` is NULL is perfectly legal.
- ayende 2y agoThat is a well structure system, yes Both cleanup for error and allocation happens in the same place That means you won't forget to call it, and the success flag is an obvious way to ha dle it
- deleted 2y ago[deleted]
- loeg 2y agoCan also use a different variable name for the success case and null out any successfully consumed temporaries. void* p1 = malloc(); if (!p1) return failure; defer { free(p1); } ... someOther->pointer = p1; p1 = NULL; return success;
- bobmcnamara 2y agoI'm not sure I'd do either for this trivial case, but it might make sense where the cleanup logic is more complex? void* p1 = malloc(...); void* p2 = malloc(...); void* p3 = malloc(...); if(p1 && p2 && p3) return {p1, p2, p3}; free(p3); free(p2); free(p1); return NULL;