First of all, if someone can reword the question to make it clearer, please do.
A common occurrence in C programming is having several resources to be initialized/al
The three most common methods I've seen so far:
1: Nested if-statements (without multiple returns for the SESE purists). With a long chain of prerequisites, this gets out of hand fast. IMO, even in simple cases this is a readability disaster and has no real advantages. I am including it because I see people do this (too) often.
uint32_t init_function() {
uint32_t erra, errb, errc, status;
A *a;
B *b;
C *c;
erra = alloc_a(&a);
if(erra) {
status = INIT_FAIL_A;
} else {
errb = alloc_b(&b);
if(errb) {
dealloc_a(&a);
status = INIT_FAIL_B;
} else {
errc = alloc_c();
if(errc) {
dealloc_b(&b);
dealloc_a(&a);
status = INIT_FAIL_C;
} else {
profit(a,b,c);
status = INIT_SUCCESS;
}
}
}
// Single return.
return status;
}
2: Multiple returns. This is my preferred method right now. THe logic is easy to follow but it's still dangerous because cleanup code has to be duplicated and it's easy to forget to deallocate something in one of the cleanup sections.
uint32_t init_function() {
uint32_t err;
A *a;
B *b;
C *c;
err = alloc_a(&a);
if(err) {
return INIT_FAIL_A;
}
err = alloc_b(&b);
if(err) {
dealloc_a(&a);
return INIT_FAIL_B;
}
err = alloc_c(&c);
if(err) {
dealloc_b(&b);
dealloc_a(&a);
return INIT_FAIL_C;
}
profit(a,b,c);
return INIT_SUCCESS;
}
3: GOTO. Many people don't like goto on principle, but this is one of the standard arguments for a valid use of goto in C programming. The advantage is that it's hard to forget a cleanup step and there is no copypasting.
uint32_t init_function() {
uint32_t status;
uint32_t err;
A *a;
B *b;
C *c;
err = alloc_a(&a);
if(err) {
status = INIT_FAIL_A;
goto LBL_FAIL_A;
}
err = alloc_b(&b);
if(err) {
status = INIT_FAIL_B;
goto LBL_FAIL_B;
}
err = alloc_c(&c);
if(err) {
status = INIT_FAIL_C;
goto LBL_FAIL_C;
}
profit(a,b,c);
status = INIT_SUCCESS;
goto LBL_SUCCESS;
LBL_FAIL_C:
dealloc_b(&b);
LBL_FAIL_B:
dealloc_a(&a);
LBL_FAIL_A:
LBL_SUCCESS:
return status;
}
Anything else I did not mention?