[ruby-list:50216] Re: 拡張ライブラリでのSEGV
From:
Hidetoshi Saito <hidetoshi.saito@...>
Date:
2015-08-09 03:58:35 UTC
List:
ruby-list #50216
須藤様
適切なご指摘ありがとうございます。
合わせて、ALLOC とxfreeのご指導もありがとうございます。
改編後のソースは正しく動作いたしました。
大変助かりました。
斎藤
===============================
斎藤 秀俊 Hidetoshi Saito
email : hidetoshi.saito@gmail.com
===============================
2015年8月9日 12:28 Kouhei Sutou <kou@cozmixng.org>:
> 須藤です。
>
> In <CALFKQwF_ZW65b0iQU_FGHcUgxZQO0a99WbK3sNwaHQiB-nUSuw@mail.gmail.com>
> "[ruby-list:50214] 拡張ライブラリでのSEGV" on Sun, 9 Aug 2015 11:02:53 +0900,
> Hidetoshi Saito <hidetoshi.saito@gmail.com> 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 <ruby.h>
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
>
> 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<len;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);
>
> }