[ruby-dev:28665] dlでメモリリークなど
From:
Masaya TARUI <tarui@...>
Date:
2006-05-22 15:03:59 UTC
List:
ruby-dev #28665
はじめまして、たるいといいます。
いつも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.