門脇と申します。
Ruby/Tkを使ってWindows上で動くクライアントプログラムを
作っています。
それまで順調に機能追加できていたものが、なんの拍子か
Segmentaion faultが発生するようになってしまいました。
環境:
Windows XP (SP3)
ruby 1.8.7 (2009-06-12 patchlevel 174) [i386-mswin32]
(ActiveScriptRuby 1.8.7(p174) with-winsock2を使用)
ActiveState ActiveTcl 8.5.8.0.291595
スクリプトを実行させると次のようなメッセージが表示され
終了してしまいます。
1 D:\X\SysproEternus\demoA>demoa5-2.rb
2 "ruby 1.8.7 (2009-06-12 patchlevel 174) [i386-mswin32]"
3 C:/Program Files/ruby-1.8/lib/ruby/1.8/tkextlib/tktable/tktable.rb:421: [BUG] Se
4 gmentation fault
5 ruby 1.8.7 (2009-06-12 patchlevel 174) [i386-mswin32]
6
7
8 This application has requested the Runtime to terminate it in an unusual way.
9 Please contact the application's support team for more information.
10
11 D:\X\SysproEternus\demoA>
(この2行目はスクリプト先頭部分にある"p RUBY_DESCRIPTION"の結果です)
「tktable.rb:421: [BUG]」の部分に表示されるライン番号は下(↓)に
示します再現方法によって変わります。
再現させるための最小限のコードは未だ発見できていません。すみません。
再現させるためのスクリプト修正には何通りかあります。
その1
問題のないスクリプトのTk::TkTable.newのパラメタに「foreground 'black'」を
追加する。
"tktable.rb:421: [BUG]"と表示されます。
1 @tktable = Tk::TkTable.new(@cvs) {|t|
2 rows num_rows
3 cols num_cols
4 ... (中略) ...
5 state 'disabled'
6 foreground 'black' # ←この行を追加する
7 x=TkcWindow.new(cvs, 5, ypos, 'window'=>t, 'anchor'=>'nw'),lower
8 }
しかし、この1行を追加しても、別の箇所のTkcLine.newを二つ無効に
するとSegmentation faultは発生しなくなります。
その2
問題のないスクリプトのifの書き方を変えると発生します。
(上記その1のTkcLine.newは有効にしたままです)
"tktable.rb:372: [BUG]"と表示されます。
1 cvs = TkCanvas.new(cf) {|c|
2 ... (中略) ...
3 }
4 cvs.bind('1', proc{|x,y| itemStartDrag cvs,x,y}, '%x %y')
5 def itemStartDrag(c,x,y)
6 # ドラッグされたオブジェクトを最前面にする
7 STDERR.print '...enter itemStartDrag'
8 $lastX = c.canvasx(x)
9 $lastY = c.canvasy(y)
10 c.gettags('current').each {|t|
11 t.raise if t!='all' && t!='current'
12 }
13 STDERR.print '...exit itemStartDrag'
14 end
この11行目を書き換えて次のようにします。
1 cvs = TkCanvas.new(cf) {|c|
2 ... (中略) ...
3 }
4 cvs.bind('1', proc{|x,y| itemStartDrag cvs,x,y}, '%x %y')
5 def itemStartDrag(c,x,y)
6 # ドラッグされたオブジェクトを最前面にする
7 STDERR.print '...enter itemStartDrag'
8 $lastX = c.canvasx(x)
9 $lastY = c.canvasy(y)
10 c.gettags('current').each {|t|
11 next if t=='all' !! t=='current'
12 t.raise
13 }
14 STDERR.print '...exit itemStartDrag'
15 end
この状態(書き換えた後)でスクリプト先頭の"p RUBY_DESCRIPTION"を
コメントにするとsegmentation faultは発生しません。
方法1からはキャンバス上のウィジットが多すぎたのかとも
考えましたが、方法2をみて多すぎたというわけではないなと
考え直しています。
Segmentation faultで示されるラインはクラスは違いますが
どちらも次の一行があります。
_setup_subst_table(KEY_TBL, PROC_TBL);
Tclの少し前のものでも同じようにsegmentation faultが発生します。
(ActiveState ActiveTcl 8.5.7.1.291226で実行しました)
アドバイスいただけたら幸いです。