トップ «前の日記(2016-09-25) 最新 次の日記(2016-10-01)» 編集

日々の破片

Subscribe with livedoor Reader
著作一覧

2016-09-30

_ コマンドラインプログラムのライブラリ化

何か問題があると、すぐさま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);
}

2003|06|07|08|09|10|11|12|
2004|01|02|03|04|05|06|07|08|09|10|11|12|
2005|01|02|03|04|05|06|07|08|09|10|11|12|
2006|01|02|03|04|05|06|07|08|09|10|11|12|
2007|01|02|03|04|05|06|07|08|09|10|11|12|
2008|01|02|03|04|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|05|06|07|08|09|10|11|12|

ジェズイットを見習え