RAIIの代用
C++だとRAIIでリソースの後始末ができる。CだとRAIIが使えないが代案を考えてみた。エラーコードが雑なのは気にしないで。
ありがちなもの。
int func(char const* filename) { FILE *fout = fopen(filename, "a+"); if (fout == NULL) { return -1; } fprintf(fout, "Logging ...\n"); if (do_something()) { fclose(fout); return -1; } fprintf(fout, "Logging ...\n"); if (do_something()) { fclose(fout); return -1; } fprintf(fout, "Logging ...\n"); fclose(fout); return 0; }
リソースの後始末が面倒だよね。
もう一つのありがちなもの。
int func(char const* filename) { int ercd = 0; FILE *fout = fopen(filename, "a+"); if (fout == NULL) { ercd = -1; goto ON_EXIT; } fprintf(fout, "Logging ...\n"); if (do_something()) { ercd = -1; goto ON_EXIT; } fprintf(fout, "Logging ...\n"); if (do_something()) { ercd = -1; goto ON_EXIT; } fprintf(fout, "Logging ...\n"); ON_EXIT: fclose(fout); return ercd; }
ercdって変数は要らないよね。
思いついたもの。
static int func_impl(FILE *fout) { if (fout == NULL) { return -1; } fprintf(fout, "Logging ...\n"); if (do_something()) { return -1; } fprintf(fout, "Logging ...\n"); if (do_something()) { return -1; } fprintf(fout, "Logging ...\n"); return 0; } int func(char const* filename) { FILE *fout = fopen(filename, "a+"); int const ercd = func_impl(fout); fclose(fout); return ercd; }
まともなコンパイラならfunc_implをインライン化するよね。