[an error occurred while processing this directive]
[an error occurred while processing this directive]
void do_f(){
struct A *a;
struct B *b;
struct C *c;
a = create_a();
b = create_b();
c = create_c();
f(a,b,c);
free_c(c);
free_b(b);
free_a(a);
}
create_a() は中で malloc() を呼んで、初期化を行い、a のアドレスを返します。
ただし初期化でエラーが発生すると、NULL を返します。
void do_f(){
struct A *a;
struct B *b;
struct C *c;
a = create_a();
if(a == NULL) return;
b = create_b();
if(b == NULL){
free_a(a);
return;
}
c = create_c();
if(c == NULL){
free_b(b);
free_a(a);
return;
}
f(a,b,c);
free_c(c);
free_b(b);
free_a(a);
}
意味的には OK ですが、free_a() を色んなところに書かないといけなかったりして、あまりきれいではありません。
void do_f(){
struct A *a;
struct B *b;
struct C *c;
a = create_a();
if(a == NULL) return;
b = create_b();
if(b == NULL) goto free_a;
c = create_c();
if(c == NULL) goto free_c;
f(a,b,c);
free_c(c);
free_b:
free_b(b);
free_a:
free_a(a);
}
goto を使うことで、かえってコピペの少ない、きれいなコードになっています。
資源の確保と解放が逆順になっているのがポイント。
void do_f(){
struct A *a = NULL;
struct B *b = NULL;
struct C *c = NULL;
do {
a = create_a();
if(a == NULL) break;
b = create_b();
if(b == NULL) break;
c = create_c();
if(c == NULL) break;
f(a,b,c);
} while(0);
if(c) free_c(c);
if(b) free_b(b);
if(a) free_a(a);
}
ループのようですが、while の条件が 0 (偽)なので、実は一回しか実行されません。