From: Yusuke Endoh Date: 2011-08-23T23:42:42+09:00 Subject: [ruby-dev:44413] [Ruby 1.9 - Bug #5217][Open] lineno is broken when source code has about 7000 lines Issue #5217 has been reported by Yusuke Endoh. ---------------------------------------- Bug #5217: lineno is broken when source code has about 7000 lines http://redmine.ruby-lang.org/issues/5217 Author: Yusuke Endoh Status: Open Priority: Normal Assignee: Category: Target version: ruby -v: ruby 1.9.4dev (2011-08-23 trunk 33019) [i686-linux] 遠藤です。 asakusa.rb で出た話だそうですが (なひさんからの伝聞) 、soap4r と simplecov を組み合わせると [BUG] bug が出るそうです。 いろいろ話を聞かせてもらった結果、以下のようにすると再現できました。 $ ruby -e 'puts "p\n" * 7000; puts "p([1"; puts "])"' > t.rb $ cat t.rb p p p # ... 7000 行ほど p ... p p $ ./ruby -rcoverage -e 'Coverage.start; load "t.rb"' 応急措置ですが、以下のパッチで直ります。 (rb_bug("bug") というアホメッセージは私の所業のようです。スミマセン) 害はないと思うので、これはこれでコミットしておこうと思います。 diff --git a/thread.c b/thread.c index 6970d8f..57a6962 100644 --- a/thread.c +++ b/thread.c @@ -4764,7 +4764,7 @@ update_coverage(rb_event_flag_t event, VALUE proc, VALUE self, ID id, VALUE klas long line = rb_sourceline() - 1; long count; if (RARRAY_PTR(coverage)[line] == Qnil) { - rb_bug("bug"); + return; } count = FIX2LONG(RARRAY_PTR(coverage)[line]) + 1; if (POSFIXABLE(count)) { しかしそもそもの原因は、iseq のバイトコードの大きさが unsigned short で管理されているために、バイトコードの大きさが 65536 を超えると行番号を 見失ってしまうという問題のような気がします。 私も最初勘違いしたのですが、行番号が 16 ビットという問題とは別であること に注意。65536 行ほど大きくなくても 7000 行くらいで発症します。 これにより、rb_vm_get_sourceline の挙動が怪しくなっています。 これは coverage に限らず、 set_trace_func(proc {|type, file, line,| p line if type == "line" }) p p p # ... 7000 行ほど p ... p p p というコードの出力が、 2 3 4 5 ... 6550 6551 6552 6553 7001 7001 7001 7001 7001 ... となります。行番号が飛んでいることがわかります。 直そうと思えば、以下のようにすれば直ります。しかしあえて short を選んで いるのは省メモリ化のためだと思いますので、これは既知の制限ということで しょうか > ささださん diff --git a/iseq.h b/iseq.h index beeacbb..9c19501 100644 --- a/iseq.h +++ b/iseq.h @@ -44,9 +44,9 @@ struct rb_compile_option_struct { }; struct iseq_insn_info_entry { - unsigned short position; - unsigned short line_no; - unsigned short sp; + unsigned long position; + unsigned long line_no; + unsigned long sp; }; struct iseq_catch_table_entry { -- Yuskue Endoh -- http://redmine.ruby-lang.org