|
View:
New views
5 Messages
—
Rating Filter:
Alert me
|
|
|
【質問】ALLOC_NとALLOCA_Nいしもと といいます。
かなり長い(数百万単位)要素数の数値配列といくつかの 係数を受け取り、それを計算して二次元配列を返す拡張ライ ブラリを作っています。 拡張ライブラリ内で配列の領域を確保する際、ALLOCA_N で確保した場合は(スタック領域の範囲内であれば)問題なく 動作しているようなのですが、同じ領域をALLOC_Nで(ヒー プ領域に?)確保するとかなり短い配列(私の環境では要素数 6266)しか扱えず、それを超えるとsegmentation faultが発 生してしまいます。私は一体何を間違ってしまっているのでし ょうか? rubyは2年ほど使っていますが、c言語を扱うのは初めてで、 ruby本やc言語関連のwebを参考にしながら見よう見まねで書 いているレベルです。アドバイス頂ければ幸いです。 使用環境: MacOSX 10.4(PowerPC) メモリ 1GB Ruby 1.8.6 SI.c -------------------------------------------------- #include "ruby.h" static VALUE si_calc6( self, ary1d, x0, y0, a ) VALUE self ; VALUE ary1d ; VALUE x0 ; VALUE y0 ; VALUE a ; { unsigned int i ; unsigned int len = 2 ; /* 引数をc言語の型に変換 */ int x0c = NUM2INT( x0 ) ; int y0c = NUM2INT( y0 ) ; double ac = NUM2DBL( a ) ; long length = RARRAY( ary1d )->len ; VALUE *items = ALLOC_N( VALUE, length ) ; /* <- これ */ /* VALUE *items = ( VALUE *)malloc( length * sizeof( VALUE ) ) ;*/ VALUE item ; VALUE t ; VALUE xt ; double y ; for ( i = 0 ; i < length ; i++){ t = INT2FIX( i + x0c ); y = NUM2DBL( rb_ary_entry( ary1d, i ) ) ; xt = rb_float_new( y0c - ( y * ac ) ) ; item = rb_ary_new3( len, t, xt ) ; items[i] = item ; } VALUE result = rb_ary_new4( length, items ) ; free( items ) ; return result ; } void Init_SI(){ VALUE msi = rb_define_module( "SI" ) ; rb_define_module_function( msi, "calc6", si_calc6, 4) ; } test.rb ----------------------------------------------- require 'SI' include SI ary=[] 6267.times{ ary.push 14238.45331 } x0=40 y0=100 a=0.01213 ext=calc6(ary,x0,y0,a) # => segmentation fault # (ary.length<=6266ならOK) ___________________ いしもと まさと(石本 将人) |
|
|
[ruby-ext:02319] Re: 【質問】ALLOC_NとALLOCA_N和田と言います。
From: mi.ml@... Subject: [ruby-ext:02318] 【質問】ALLOC_NとALLOCA_N Date: Sat, 07 Apr 2007 14:07:47 -0700 VALUE型をヒープに確保した場合は rb_gc_markという関数でそのことをRuby側に 伝えてやる必要があるようです。 ですので、以下のようにすればいいのでは ないでしょうか? for ( i = 0 ; i < length ; i++){ t = INT2FIX( i + x0c ); y = NUM2DBL( rb_ary_entry( ary1d, i ) ) ; xt = rb_float_new( y0c - ( y * ac ) ) ; item = rb_ary_new3( len, t, xt ) ; items[i] = item ; rb_gc_mark(items[i]); /* <--- これを追加 */ } 青木さんの http://i.loveruby.net/w/RubyExtensionProgrammingGuide.html を参考にしました。 |
|
|
[ruby-ext:02320] Re: 【質問】ALLOC_NとALLOCA_Nなかだです。
At Sun, 08 Apr 2007 13:35:28 +0900 (JST), ysk wrote in [ruby-ext:02319]: > VALUE型をヒープに確保した場合は > rb_gc_markという関数でそのことをRuby側に > 伝えてやる必要があるようです。 rb_gc_mark()をmark用関数以外から呼んではいけません。 この場合はresultを先に確保しておいて、そのptrを使うということで いいのではないでしょうか。 static VALUE si_calc6(self, ary1d, x0, y0, a) VALUE self; VALUE ary1d; VALUE x0; VALUE y0; VALUE a; { unsigned int i; /* 引数をc言語の型に変換 */ int x0c = NUM2INT(x0); int y0c = NUM2INT(y0); double ac = NUM2DBL(a); long length = RARRAY(ary1d)->len; VALUE result = rb_ary_new2(length); VALUE *items = RARRAY_PTR(result); VALUE klass = RBASIC(result)->klass; VALUE item; VALUE t; VALUE xt; double y; RBASIC(result)->klass = 0; for (i = 0; i < length; i++){ t = INT2FIX(i + x0c); y = NUM2DBL(rb_ary_entry(ary1d, i)); xt = rb_float_new(y0c - (y * ac)); item = rb_ary_new3(2, t, xt); items[i] = item; } RBASIC(result)->klass = klass; return result; } -- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦 |
|
|
[ruby-ext:02321] Re: 【質問】ALLOC_NとALLOCA_N和田と言います。
From: Nobuyoshi Nakada <nobu@...> Subject: [ruby-ext:02320] Re: 【質問】ALLOC_NとALLOCA_N Date: Sun, 08 Apr 2007 16:23:52 +0900 > rb_gc_mark()をmark用関数以外から呼んではいけません。 そうでしたか。よくわからずに答えるのはよくなかったですね。 失礼しました。 |
|
|
[ruby-ext:02323] Re: __R e:_【質問】ALLOC_NとALLOCA_N質問者の いしもと です。
和田さん、中田さん、アドバイスありがとうございます。 知らないことばかりで、とても勉強になります。 ただ、お二方のアドバイスを実行しましたが、悲しいこと に望むような結果は得られませんでした。 以下、現状報告です。 【和田さん案】 かなり長い配列を引数に指定してもseg faultしなくなった。 しかし、returnされた配列をruby program内で扱おうとす るとseg faultが発生する。(引数配列の長さによっては発生 しないこともあるが、returnされる配列が少しおかしい。) (例1) ary.length==3,000,000 result=calc6(ary, etc) p result[0] => seg fault (例2) ary.length==1,000,000 result=calc6(ary, etc) p result[0] => value # ? p result[-1] => [index, value] # ok 【中田さん案】 seg faultはしなくなった。しかし、returnされる配列が 空になっている。 (例) result=calc6(ary, etc) p result.length => 0 現在、和田さんが紹介して下さった青木さんのサイトや rhgなどを見ながら(にわか)猛勉強中です。volatileあた りも気になっていますが、それ以前に基礎を固める必要も 痛感しています... 引き続きアドバイスなど頂けましたら幸いです。 ___________________ いしもと まさと(石本 将人) 2007年04月08日 16:23 の "Nobuyoshi Nakada" <nobu@...>のメール: >なかだです。 > >At Sun, 08 Apr 2007 13:35:28 +0900 (JST), >ysk wrote in [ruby-ext:02319]: >> VALUE型をヒープに確保した場合は >> rb_gc_markという関数でそのことをRuby側に >> 伝えてやる必要があるようです。 > >rb_gc_mark()をmark用関数以外から呼んではいけません。 > >この場合はresultを先に確保しておいて、そのptrを使うということで >いいのではないでしょうか。 > >static VALUE >si_calc6(self, ary1d, x0, y0, a) > VALUE self; > VALUE ary1d; > VALUE x0; > VALUE y0; > VALUE a; >{ > unsigned int i; > /* 引数をc言語の型に変換 */ > int x0c = NUM2INT(x0); > int y0c = NUM2INT(y0); > double ac = NUM2DBL(a); > long length = RARRAY(ary1d)->len; > VALUE result = rb_ary_new2(length); > VALUE *items = RARRAY_PTR(result); > VALUE klass = RBASIC(result)->klass; > > VALUE item; > VALUE t; > VALUE xt; > double y; > > RBASIC(result)->klass = 0; > for (i = 0; i < length; i++){ > t = INT2FIX(i + x0c); > y = NUM2DBL(rb_ary_entry(ary1d, i)); > xt = rb_float_new(y0c - (y * ac)); > item = rb_ary_new3(2, t, xt); > items[i] = item; > } > RBASIC(result)->klass = klass; > > return result; >} > >-- >--- 僕の前にBugはない。 >--- 僕の後ろにBugはできる。 > 中田 伸悦 > > |
| Free embeddable forum powered by Nabble | Forum Help |