...
Code Block |
---|
|
typedef struct object { // A generic struct -- The contents don't matter
int propertyA, propertyB, propertyC;
} object_t;
interrno_t do_something(void){
FILE *fin;
object_t *obj1, *obj2;
errno_t ret_val;
fin = fopen("some_file", "r");
if (fin == NULL){
return -1errno;
}
obj1 = malloc(sizeof(object_t));
if (obj1 == NULL){
ret_val = errno;
fclose(fin);
return -1ret_val;
}
obj2 = malloc(sizeof(object_t));
if (obj2 == NULL){
ret_val = errno;
fclose(fin);
return -1ret_val; // Forgot to free obj1 !!
}
// ... more code ...
}
|
...
In this revised version, we have used a goto-chain in replacement of each individual return segment. If there is no error, control flow will fall through to the SUCCESS
label, release all of the resources and return RET_SUCCESS
NOERR
. In the case of an error, the return value will be set to RET_ERROR
errno
, control flow will jump to the proper failure label, and the appropriate resources will be released before returning.
Wiki Markup |
---|
Please note that these examples assume {{errno_t}} and {{NOERR}} to be defined, as requested by \[[DCL09-C. Declare functions that return an errno error code with a return type of errno_t|DCL09-C. Declare functions that return an errno error code with a return type of errno_t]\]. An equivalent compatible example would define {{errno_t}} as an {{int}} and {{NOERR}} as zero. |
Code Block |
---|
|
// ... assume the same struct as above ...
#define RET_SUCCESS 0
#define RET_ERROR -1
int errno_t do_something(void){
FILE *fin;
object_t *obj1, *obj2;
interrno_t ret_val = RET_SUCCESSNOERR; // Initially assume a successful return value
fin = fopen("some_file", "r");
if (fin == NULL){
ret_val = RET_ERRORerrno;
goto FAIL_FIN;
}
obj1 = malloc(sizeof(object_t));
if (obj1 == NULL){
ret_val = RET_ERRORerrno;
goto FAIL_OBJ1;
}
obj2 = malloc(sizeof(object_t));
if (obj2 == NULL){
ret_val = RET_ERRORerrno;
goto FAIL_OBJ2;
}
// ... more code ...
SUCCESS: // Free everything
free(obj2);
FAIL_OBJ2: // Otherwise, free only the objects we allocated
free(obj1);
FAIL_OBJ1:
fclose(fin);
FAIL_FIN:
return ret_val;
}
|
...