読者です 読者をやめる 読者になる 読者になる

メモリ破壊の現場を見つけるTips

RubyAdventJP GC Ruby

(この記事はRuby Advent Calendar jp: 2009 : ATNDの4日目です。前日はmrknさんでした)
 
健全なるRubyistであれば、RubyGCをいじることが週に一度はあるでしょう。
そのときに困るのが、GCをいじってしまったことによるバグの修正です。
GCをいじるというのは想像以上に難しく、少しでも書き間違えるとメモリ破壊が発生します。
そのときに使えるTipsをこの記事で書くことにします。
 
みなさんご存じの通り、メモリ破壊というのは原因を特定するのが困難です。
これは問題が発覚する場所とメモリ破壊が起こった現場が位置的に遠いことに起因しています。
偉大なるハッカーのまつもとさんですら、その発見は困難です。
 
[ruby-dev:38628] Re: [BUG: trunk] called on terminated object

まつもと ゆきひろです

In message "Re: [ruby-dev:38625] Re: [BUG: trunk] called on terminated object"
    on Mon, 15 Jun 2009 18:10:51 +0900, Tanaka Akira  writes:

(中略)
ということは、GC は後者を回収したのに前者を回収しなかったっ
てことで、それは変じゃないですか?
変なのは確かです。が、だれがオブジェクトを壊しているのか見付 けられませんでした。

 
しかし、上記のポストにはとても素晴らしい返信がありました。
[ruby-dev:38634] Re: [BUG: trunk] called on terminated object

(中略)
> 変なのは確かです。が、だれがオブジェクトを壊しているのか見付
> けられませんでした。

調べたところ、壊しているというか、隠しているところは 20分で
見つかりました。

そうです。akrさんです!!(イイハナシダナー)
 
さて、akrさんはどのようにしてメモリ破壊を見つけたのでしょうか?
正解は次の通りです。

なお、コツは、
 * echo 0 > /proc/sys/kernel/randomize_va_space
 * watchpoint
でしょうか。

 

/proc/sys/kernel/randomize_va_space

もう結果しか書きませんけど、以下のコマンドを打つとプログラム実行時のメ
モリ領域のアドレスが変わらなくなります。

echo 0 > /proc/sys/kernel/randomize_va_space

そのため、一度SEGVが起きて「あ、このアドレスのオブジェクトがおかしい」とわかれば、
gdbで直接をアドレス指定してwatchpointを張ることができます。
なんでランダムになってんのー?とかはLinuxキーワード - ASLR:ITproを見ること。
 

watchpoint

watchpointとは名前の通り、gdbである値の変化を検知するコマンドです。

(gdb) watch hoge

上記の様にコマンドを打つとhoge変数が書き換わった瞬間に処理が停止し、デバッガに処理が移ります。
前節のテクニックと併用し、アドレスを直接指定することで、オブジェクト内の変数が
書き換わった箇所を調べることができます。
 

結論

akrさんはどうやら以下のようなコマンドを打って、メモリ破壊している位置を見つけたようです。

(gdb) watch (*(struct RBasic *) 136308180).klass
Watchpoint 4: (*(struct RBasic *) 136308180).klass
(gdb) c
Continuing.
Hardware watchpoint 4: (*(struct RBasic *) 136308180).klass

Old value = 136379420
New value = 0
iseq_compile_each (iseq=0x82c1888, ret=0xbfffaa98, node=0x81fe5c0, poped=0) at compile.c:4409
4409                ADD_INSN1(ret, nd_line(node), putstring, node->nd_lit);
(gdb) bt
#0  iseq_compile_each (iseq=0x82c1888, ret=0xbfffaa98, node=0x81fe5c0, poped=0) at compile.c:4409
...以下略

このようにruby-devには深イイ話が転がっていますので、みなさんも購読しましょうね!
(明日、5日目は「Mr.G」ことjugyoさんです。"g is wabi-sabi..")