Another way to do cleanup in C?
Another way to do cleanup in C?
Consider this program:
int main(void) { int* i = malloc(sizeof(int)); int* j = malloc(sizeof(int)); } However this is a naive approach, because malloc may fail and the pointers are not free'd.
So you can do this:
int main(void) { int* i; int* j; if ((i = malloc(sizeof(int)) < 0) { return -1; } if ((j = malloc(sizeof(int)) < 0) { free(i); return -1; } free(i); free(j); } However I consider this very error-prone. Consider having to assign 20 pointers, in the last malloc error case, you have to free 19 variables and then return -1.
I also know atexit, which can help me to write it like this:
int* i; int* j; void del_i(void) { free(i); } void del_j(void) { free(j); } int main(void) { if ((i = malloc(sizeof(int)) < 0) { return -1; } else { atexit(del_i); } if ((j = malloc(sizeof(int)) < 0) { return -1; } else { atexit(del_j); } } Which is better, but I dislike having to declare all pointers as global. Is there some way to combine these two approaches, basically:
- Having destructors for pointers, which can be either executed directly or be used with
atexit. - Having pointers local to functions.
Answer by Schafwolle for Another way to do cleanup in C?
int main(void) { int* i = NULL; // Init with NULL otherwise free on none NULL possible int* j = NULLL; if (!(i = malloc(sizeof(int))) { goto exit; } if (!(j = malloc(sizeof(int))) { goto exit; } ... exit: free(i); free(j); ... return err; } This is something you can solve with goto statements.
Answer by dasblinkenlight for Another way to do cleanup in C?
First, this will not detect malloc failure:
if ((i = malloc(sizeof(int)) < 0) { return -1; } malloc returns NULL on failure, not a negative number.
Second, atexit is good for cleaning up static and global objects. It is not a good idea to make local objects global only to use them inside atexit.
A better approach is to make a struct for all related pointers that you need to allocate in an all-or-nothing unit, define a function for freeing them all at once, and write a function that allocates them one by one with memory checking on each allocation:
typedef struct AllOrNothing { double *dPtr; int *iPtr; float *fPtr; size_t n; } AllOrNothing; void freeAllOrNothing(AllOrNothing *ptr) { free(ptr->dPtr); free(ptr->iPtr); free(ptr->fPtr); free(ptr); } int allocateAllOrNothing(size_t n, AllOrNothing **res) { *res = malloc(sizeof(AllOrNothing)); if (*res == NULL) { return -1; } // Freeing NULL is allowed by the standard. // Set all pointers to NULL upfront, so we can free them // regardless of the stage at which the allocation fails (*res)->dPtr = NULL; (*res)->iPtr = NULL; (*res)->fPtr = NULL; (*res)->n = n; (*res)->dPtr = malloc(n*sizeof(double)); if ((*res)->dPtr == NULL) { free(*res); *res = NULL; return -1; } (*res)->fPtr = malloc(n*sizeof(float)); if ((*res)->fPtr == NULL) { free(*res); *res = NULL; return -1; } (*res)->iPtr = malloc(n*sizeof(int)); if ((*res)->iPtr == NULL) { free(*res); *res = NULL; return -1; } return 0; } Answer by Tommy for Another way to do cleanup in C?
free on NULL is defined to be a safe no-op. So a non-jumping variation could be:
int *i = malloc(sizeof(int)); int *j = malloc(sizeof(int)); if(i && j) { // do some work } free(i); free(j); Answer by abelenky for Another way to do cleanup in C?
int main(void) { int* i = NULL; int* j = NULL; bool success = false; do { i = malloc(sizeof(int)); if (NULL == i) break; j = malloc(sizeof(int)); if (NULL == j) break; success = true; } while (0); if (!success) { printf("Something failed!"); } else { printf("All succeeded!"); // Do more work } free(i); free(j); return (success? 0 : 1); } Answer by Mukesh for Another way to do cleanup in C?
int *i=NULL,*j=NULL; if(!(i=malloc(sizeof(int)))) goto EXIT; if(!(j=malloc(sizeof(int)))) goto EXIT; /* do some work */ return 0; EXIT: free(i); free(j); exit(EXIT_FAILURE); Although goto is considered a bad programming practice but here we can use it to get our task done with ease and simplicity
Answer by chux for Another way to do cleanup in C?
Avoid multiple exit points. Avoid interlacing allocation and error handling. Follows a clean order of operation:
- Declare, allocate and initialize resources..
- If all successful, do the task.
- Clean-up.
- Return status.
// Do all allocations first, test their `NULL`-ness, then free them all. int main(void) { // Allocate resources // declare and allocate in one step int* i = malloc(sizeof *i); double* j = malloc(sizeof *j); // Test for acceptability bool ok = i && j; // Perform the main body of code if (ok) { ; // do normal process in the code; } // free resources free(i); free(j); // return status return ok ? 0 : -1; } Fatal error: Call to a member function getElementsByTagName() on a non-object in D:\XAMPP INSTALLASTION\xampp\htdocs\endunpratama9i\www-stackoverflow-info-proses.php on line 72
0 comments:
Post a Comment