"arena overflow error" で mruby がとまるときの対策
@masuidrive ひとつのC関数の中でオブジェクト割り当てすぎの時に起きるエラーです。array.cのinspect_aryを参考に、一時オブジェクトを作ってる部分をmrb_gc_arena_saveとmrb_gc_arena_restoreで囲んでください。
— Yukihiro Matsumoto (@yukihiro_matz) July 6, 2012
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