[#28653] create header (Re: Re: ossl_cipher.c:124: warning: control reaches end of non-void function) — "Nobuyoshi Nakada" <nobu@...>

なかだです。

8 messages 2006/05/18

[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.

In This Thread

Prev Next