なかだです。

At Sat, 15 Mar 2008 15:18:33 +0900,
Nobuyoshi Nakada wrote in [ruby-dev:34061]:
> At Sat, 15 Mar 2008 12:43:25 +0900,
> rubikitch / ruby-lang.org wrote in [ruby-dev:34059]:
> > $stdoutに別のオブジェクトを指定した場合、putsでSEGVります。
> > Ruby 1.9.0では大丈夫です。
> 
> スタックオーバーフローしてますね。原因は、r15564でKernel#putsが
> $stdout.putsを呼ぶようになったのですが、このLoggerはputsメソッド
> を持っていないのでKernel#putsがまた呼ばれることになるためです。
> 
> > class Logger
> >   def write(obj)
> >     STDOUT.print Time.now.strftime("%Y/%m/%d %H:%M:%S:"), obj
> >   end
> > end
> > $stdout = Logger.new
> 
> 対応としては二つほど思い付きますが、どうしましょうか。
> 
> 1. r15564をrevertする。
> 
> 2. $stdoutの仕様を変えて、writeだけでなくputs,putcも定義必須にす
>    る。Kernel#putsを呼んでしまうのを防ぐために、rb_f_putcと
>    rb_f_putsではrb_funcall2ではなくrb_funcall3を使うようにする。

もう一つ思い付きました。

3. selfが$stdoutならIO#putc,IO#putsを直接呼ぶ、$stdout以外なら
   $stdoutのメソッドを呼ぶ。


Index: io.c =================================================================== --- io.c (revision 15780) +++ io.c (working copy) @@ -4486,4 +4486,7 @@ static VALUE rb_f_putc(VALUE recv, VALUE ch) { + if (recv == rb_stdout) { + return rb_io_putc(recv, ch); + } return rb_funcall2(rb_stdout, rb_intern("putc"), 1, &ch); } @@ -4563,6 +4566,9 @@ rb_io_puts(int argc, VALUE *argv, VALUE static VALUE -rb_f_puts(int argc, VALUE *argv) +rb_f_puts(int argc, VALUE *argv, VALUE recv) { + if (recv == rb_stdout) { + return rb_io_puts(argc, argv, recv); + } return rb_funcall2(rb_stdout, rb_intern("puts"), argc, argv); }
-- --- 僕の前にBugはない。 --- 僕の後ろにBugはできる。 中田 伸悦