著作一覧 |
何か問題があると、すぐさまexit(n)とかで抜けてしまうプログラムをライブラリにしなければならず、いろいろ弱ったが、考えてみればそのための大域脱出だった。
たとえば元のプログラムが
#inculde <stdio.h> // ... int fatal(char* tmpl, ...) { va_list argp; ... vprintf(tmpl, argp); exit(4); } void do_extract(char* src, char* dst) { ... } int main(int argc, char* argv[]) { if (!strcmp(argv[1], "extract")) do_extract(argv[2], argv[3]); else if (... }
だった場合、
#include <setjmp.h> static jmp_buf env; int fatal(char* impl, ...) { va_list argp; ... vprintf(tmpl, argp); longjmp(env, 4); } int do_extract(char* src, char* dst) { int exitcode = setjmp(env); if (exitcode) return exitcode; // 元の処理 return 0; }
で、問題はもしこのライブラリを呼び出すプログラムが延々と動作する場合で、かつライブラリの中でmallocやfopenをしまくると、巻き戻しがされないことだ。
その場合は、jmp_bufをスタックにすれば良いのかな?
static int ijmp = 0; static jmp_buf env[32]; int fatal(char* impl, ...) { va_list argp; ... vprintf(tmpl, argp); longjmp(env[--ijmp], 4); } void memallocfn() { char* mem = NULL; int exitcode = setjmp(env[ijmp++]); if (exitcode) { free(mem); longjmp(env[--ijmp], exitcode); } mem = malloc(BUFF_SIZE); if (!mem) fatal("can't allocate memblock (%d) %d", BUFF_SIZE, errno); ... free(mem); }
ジェズイットを見習え |