From: Masaya TARUI Date: 2006-05-23T00:03:59+09:00 Subject: [ruby-dev:28665] dlでメモリリークなど はじめまして、たるいといいます。 いつもRubyを使わせてもらっています。このようなソフトウェアを世に出して いただいき、まつもと氏を始め、皆様に感謝。 特にruby/dlはwindowsのAPIを触るのに有効活用させてもらっています。 今回はdlを使っていてメモリリークでアプリケーションが落ちてしまった為に 投稿します。またその時ソースを見ていてAlignの取り方にバグがあり構造体 によってはデータが正しく扱えないのに気づいたのでそれも。 動作チェックをした環境は以下になります。 ruby 1.8.4 (2005-12-24) [i386-mswin32] なお、これらはruby1.9.0のdl2では問題ありませんでした。 1.メモリリーク require 'dl' require 'dl/import' require 'dl/struct' extend DL::Importable size=100000 S = struct [ "char i[#{size}]" ] a=S.malloc data=" " *(size-1) loop { a.i = data } でかなり早いタイミングでメモリ確保が出来なくなり落ちます。 ary2caryの先でxmallocで作業領域を確保して開放していないのが原因です。 とりあえず、以下で問題はなくなりました。 (これが正しい作法かはわかりませんが) --- ptr.c.orig 2003-10-22 23:29:20.000000000 +0900 +++ ptr.c 2006-05-22 23:00:19.000000000 +0900 @@ -912,4 +912,5 @@ memimg = ary2cary(data->stype[i], val, &memsize); memcpy((char *)data->ptr + offset, memimg, memsize); + dlfree(memimg); return val; } @@ -982,4 +983,5 @@ memimg = ary2cary(data->stype[i], val, NULL); memcpy(data->ptr, memimg, memsize); + dlfree(memimg); } } ---------------------------------------------ここまで 2. align require 'dl' require 'dl/import' require 'dl/struct' extend DL::Importable S= struct [ "char c1", "int i1", "char c2", "int i2", ] a=S.malloc puts a.to_ptr.to_s(a.size).unpack("C*").map{|c| "%02x" % c}.join(",") a.i1=0x11121314 a.i2=0x21222324 puts a.to_ptr.to_s(a.size).unpack("C*").map{|c| "%02x" % c}.join(",") a.c1=0xf1 a.c2=0xf2 puts a.to_ptr.to_s(a.size).unpack("C*").map{|c| "%02x" % c}.join(",") 構造体に値をいれながら、構造体の実際のデータ配置を出力しています。 期待出力としては、 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 00,00,00,00,14,13,12,11,00,00,00,00,24,23,22,21 f1,00,00,00,14,13,12,11,f2,00,00,00,24,23,22,21 ですが実際は 00,00,00,00,00,00,00,00,00,00,00,00,00,00,00,00 00,00,00,00,14,13,12,11,24,23,22,21,00,00,00,00 f1,00,00,00,14,f2,12,11,24,23,22,21,00,00,00,00 となり誤った配置どころか上書きしてしまっています。 アライメントを取るルーチンが構造体のメンバ名判定の中に入ってしまってお り、まともに実行されていないのが原因です。以下、場所を入れ替えてIndent しなおしただけです。 --- ptr.c~ 2006-05-22 23:00:19.000000000 +0900 +++ ptr.c 2006-05-22 23:19:23.000000000 +0900 @@ -754,30 +754,30 @@ case DLPTR_CTYPE_STRUCT: for (i=0; i < data->ids_num; i++) { + switch (data->stype[i]) { + case 'I': + DLALIGN(data->ptr,offset,INT_ALIGN); + break; + case 'L': + DLALIGN(data->ptr,offset,LONG_ALIGN); + break; + case 'P': + case 'S': + DLALIGN(data->ptr,offset,VOIDP_ALIGN); + break; + case 'F': + DLALIGN(data->ptr,offset,FLOAT_ALIGN); + break; + case 'D': + DLALIGN(data->ptr,offset,DOUBLE_ALIGN); + break; + case 'C': + break; + case 'H': + DLALIGN(data->ptr,offset,SHORT_ALIGN); + break; + default: + rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]); + } if (data->ids[i] == id) { - switch (data->stype[i]) { - case 'I': - DLALIGN(data->ptr,offset,INT_ALIGN); - break; - case 'L': - DLALIGN(data->ptr,offset,LONG_ALIGN); - break; - case 'P': - case 'S': - DLALIGN(data->ptr,offset,VOIDP_ALIGN); - break; - case 'F': - DLALIGN(data->ptr,offset,FLOAT_ALIGN); - break; - case 'D': - DLALIGN(data->ptr,offset,DOUBLE_ALIGN); - break; - case 'C': - break; - case 'H': - DLALIGN(data->ptr,offset,SHORT_ALIGN); - break; - default: - rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]); - } return cary2ary((char *)data->ptr + offset, data->stype[i], data->ssize[i]); } @@ -884,30 +884,30 @@ offset = 0; for (i=0; i < data->ids_num; i++) { + switch (data->stype[i]) { + case 'I': + DLALIGN(data->ptr,offset,INT_ALIGN); + break; + case 'L': + DLALIGN(data->ptr,offset,LONG_ALIGN); + break; + case 'P': + case 'S': + DLALIGN(data->ptr,offset,VOIDP_ALIGN); + break; + case 'D': + DLALIGN(data->ptr,offset,DOUBLE_ALIGN); + break; + case 'F': + DLALIGN(data->ptr,offset,FLOAT_ALIGN); + break; + case 'C': + break; + case 'H': + DLALIGN(data->ptr,offset,SHORT_ALIGN); + break; + default: + rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]); + } if (data->ids[i] == id) { - switch (data->stype[i]) { - case 'I': - DLALIGN(data->ptr,offset,INT_ALIGN); - break; - case 'L': - DLALIGN(data->ptr,offset,LONG_ALIGN); - break; - case 'P': - case 'S': - DLALIGN(data->ptr,offset,VOIDP_ALIGN); - break; - case 'D': - DLALIGN(data->ptr,offset,DOUBLE_ALIGN); - break; - case 'F': - DLALIGN(data->ptr,offset,FLOAT_ALIGN); - break; - case 'C': - break; - case 'H': - DLALIGN(data->ptr,offset,SHORT_ALIGN); - break; - default: - rb_raise(rb_eDLTypeError, "unsupported type '%c'", data->stype[i]); - } memimg = ary2cary(data->stype[i], val, &memsize); memcpy((char *)data->ptr + offset, memimg, memsize); ---------------------------------------------ここまで 以上 -- 樽家昌也(Masaya TARUI) No Tool,No Life.