bool function_with_cleanup(void) {
int *buffer1 = NULL;
int *buffer2 = NULL;
FILE *file = NULL;
bool success = false;
// Allocate first resource
buffer1 = malloc(sizeof(int) * 100);
if (buffer1) {
// Allocate second resource
buffer2 = malloc(sizeof(int) * 200);
if (buffer2) {
// Open a file
file = fopen("data.txt", "r");
if (file) {
// Do work with all resources...
fclose(file);
success = true; // Only set to true if everything succeeded
}
free(buffer2);
}
free(buffer1);
}
return success;
}
Much shorter and more straightforward.
One-time loops with break also work if you're not doing the resource allocation in another loop:
bool function_with_cleanup(void) {
int *buffer1 = NULL;
int *buffer2 = NULL;
FILE *file = NULL;
bool success = false;
do { // One-time loop to break out of on error
// Allocate first resource
buffer1 = malloc(sizeof(int) * 100);
if (!buffer1) {
break; // Error, jump to cleanup
}
// Allocate second resource
buffer2 = malloc(sizeof(int) * 200);
if (!buffer2) {
break; // Error, jump to cleanup
}
// Open a file
file = fopen("data.txt", "r");
if (!file) {
break; // Error, jump to cleanup
}
// Do work with all resources...
success = true; // Only set to true if everything succeeded
} while(false);
// Free resources in reverse order of acquisition
if (file) fclose(file);
free(buffer2); // free() is safe on NULL pointers
free(buffer1);
return success;
}
Still simpler to follow than goto IMHO. Both these patterns work in other languages without goto too, e.g. Python.
One-time loops with break also work if you're not doing the resource allocation in another loop:
Still simpler to follow than goto IMHO. Both these patterns work in other languages without goto too, e.g. Python.