From: Hidetoshi Saito Date: 2015-08-09T12:58:35+09:00 Subject: [ruby-list:50216] Re: 拡張ライブラリでのSEGV 須藤様 適切なご指摘ありがとうございます。 合わせて、ALLOC とxfreeのご指導もありがとうございます。 改編後のソースは正しく動作いたしました。 大変助かりました。 斎藤 =============================== 斎藤 秀俊 Hidetoshi Saito email : hidetoshi.saito@gmail.com =============================== 2015年8月9日 12:28 Kouhei Sutou : > 須藤です。 > > In > "[ruby-list:50214] 拡張ライブラリでのSEGV" on Sun, 9 Aug 2015 11:02:53 +0900, > Hidetoshi Saito wrote: > >> static VALUE clsdebug_alloc(VALUE klass) >> { >> struct debugobj *ptr = ALLOC(struct debugobj); > > ここに > > ptr->ary = Qnil; > > を入れるといいと思います。 > >> return Data_Wrap_Struct(klass, clsdebug_mark, -1, ptr); >> } > > clsdebug_alloc()が呼ばれた後、 > >> static VALUE >> rb_clsdebug_init(VALUE self) >> { >> char *p_str; >> char str[]="abcdefghijklmns"; >> int i,len; >> >> struct debugobj *ptr; >> Data_Get_Struct(self, struct debugobj, ptr); >> >> p_str=str; >> len = strlen(p_str); > > ここまでの間にGCが走るとptr->aryの中身がどうなっているかわか > らないのでrb_gc_mark(ptr->ary)したときに落ちる可能性がありま > す。 > >> ptr->ary = rb_ary_new(); > > > > ところで、ALLOC()した領域をxfree()した方がいいんじゃないかなぁ > と思いました。 > > 私が拡張ライブラリーを書くときはXXX_alloc()ではALLOC()せずに、 > NULLをData_Wrap_Struct()するだけにして、initializeに対応する > Cの関数の方でALLOC()(を使ったり、別の方法を使ったりしてメモ > リーを確保)しています。(見たらそうしていました。) > > > ということで、私ならこんな感じにします。 > > #include > #include > #include > #include > > struct debugobj{ > VALUE ary; > }; > > static void clsdebug_mark(struct debugobj *ptr) > { > rb_gc_mark(ptr->ary); > } > > static void clsdebug_free(struct debugobj *ptr) > { > xfree(ptr); > } > > static VALUE clsdebug_alloc(VALUE klass) > { > return Data_Wrap_Struct(klass, clsdebug_mark, clsdebug_free, NULL); > } > > static VALUE > rb_clsdebug_init(VALUE self) > { > char *p_str; > char str[]="abcdefghijklmns"; > int i,len; > > struct debugobj *ptr = NULL; > ptr = ALLOC(struct debugobj); > ptr->ary = Qnil; > DATA_PTR(self) = ptr; > > p_str=str; > len = strlen(p_str); > ptr->ary = rb_ary_new(); > for(i=0;i { > volatile VALUE v = rb_str_new(p_str+i,1); > rb_ary_push(ptr->ary,v); > } > return Qnil; > } > > static VALUE > rb_clsdebug_ary(VALUE self) > { > struct debugobj *ptr; > Data_Get_Struct(self, struct debugobj, ptr); > volatile VALUE v = ptr->ary; > return v; > } > > > void Init_libdebug(void) { > VALUE libDebug; > VALUE clsdebug; > > libDebug = rb_define_module("LibDebug"); > clsdebug = rb_define_class_under(libDebug, "Clsdebug", rb_cObject); > > rb_define_alloc_func(clsdebug, clsdebug_alloc); > rb_define_method(clsdebug, "initialize", > RUBY_METHOD_FUNC(rb_clsdebug_init), 0); > rb_define_method(clsdebug, "to_a", RUBY_METHOD_FUNC(rb_clsdebug_ary), 0); > > }