tokuhirom's Blog

"arena overflow error" で mruby がとまるときの対策

mrb_gc_arena_save と mrb_gc_arena_restore でかこめばいい。

具体的には以下の箇所です。

static mrb_value
inspect_ary(mrb_state *mrb, mrb_value ary, mrb_value list)
{
  int i;
  mrb_value s, arystr;
  char head[] = { '[' };
  char sep[] = { ',', ' ' };
  char tail[] = { ']' };

  /* check recursive */
  for(i=0; i<RARRAY_LEN(list); i++) {
    if (mrb_obj_equal(mrb, ary, RARRAY_PTR(list)[i])) {
      return mrb_str_new(mrb, "[...]", 5);
    }
  }

  mrb_ary_push(mrb, list, ary);

  arystr = mrb_str_buf_new(mrb, 64);
  mrb_str_buf_cat(mrb, arystr, head, sizeof(head));

  for(i=0; i<RARRAY_LEN(ary); i++) {
    int ai = mrb_gc_arena_save(mrb); // ← ここ

    if (i > 0) {
      mrb_str_buf_cat(mrb, arystr, sep, sizeof(sep));
    }
    if (mrb_type(RARRAY_PTR(ary)[i]) == MRB_TT_ARRAY) {
      s = inspect_ary(mrb, RARRAY_PTR(ary)[i], list);
    } else {
      s = mrb_inspect(mrb, RARRAY_PTR(ary)[i]);
    }
    mrb_str_buf_cat(mrb, arystr, RSTRING_PTR(s), RSTRING_LEN(s));
    mrb_gc_arena_restore(mrb, ai); // ← ここ
  }

  mrb_str_buf_cat(mrb, arystr, tail, sizeof(tail));
  mrb_ary_pop(mrb, list);

  return arystr;
}

詳細な解説はこのへんが詳しい。
http://www.dzeta.jp/~junjis/code_reading/index.php?mruby%2FGC%BD%E8%CD%FD%A4%F2%C6%C9%A4%E0