I'm working on a school project and the teacher asked us to free all resources at program's termination.
I'm struggling to find a way to write more readable and/or less code to manage that, specifically considering this is made more complex by the fact that different exit points will probably have a different set of resources to free.
The simplest and most messy solution seems to be this(exit points are represented as "some_sys_call" calls that return -1):
char *a = malloc(1);
if(some_sys_call() == -1){
free(a);
return -1;
}
//b is needed until the end
char *b = malloc(1);
if(some_sys_call() == -1){
free(a);
free(b);
return -1;
}
//c is needed until the end
char *c = malloc(1);
//a is no longer needed from here on, so it's freed right away
free(a);
if(some_sys_call() == -1){
free(b);
free(c);
return -1;
}
//Exit point when there are no errors
free(b);
free(c);
return 0;
This doesn't seem very appealing for obvious reasons: you need to write a lot of code especially when you have a lot of resources, making the code bloated with frees and less readable. Of course you can't simply write a macro or function that frees all the resources and call it at each exit point, like this:
#define free_all free(a); \
free(b); \
free(c);
You could technically define different macros/functions for each set of frees:
#define free_1 free(a);
#define free_2 free(a); \
free(b);
...
This would make the "actual" code more readable but would still require you to write a lot of different macros and doesn't seem to me like a good solution either.
Is this considered a common problem? How is this usually handled?
atexit
and in that function perform the cleanups. – Gelationfree(a); if(some_sys_call() == -1){ free(a);
looks like a double free error. Was that your intent? – Haff