Ruby で backtrace を取得する

こんにちは、masm11 です。

Ruby で、「このコードのここに来た時、どこからどう呼ばれてきたのか知りたい!」ということは ありませんか? よくあると思います。 おそらく最近の IDE なら、問題なく、いつでも見られるのでしょう、きっと。 しかし私はそういった便利な IDE を使っておらず、基本いわゆる printf デバッグです。 こういう場合、自前でなんとか取得する方法が必要です。

今回は、その方法と、それに関連した話題をご紹介します。

Ruby で取得する方法

みなさんは、例外が発生すると、その例外から backtrace を取得できることは ご存知だと思います。そこで、この方法を使います。

begin
  raise 'dummy'
rescue => e
  puts e.backtrace.join("\n")
end

こんな感じですね。例外を投げて、即 rescue します。e.backtrace には backtrace が格納されています。これで backtrace を puts することができます。

luna:~ % ruby test.rb
test.rb:5:in `main'
test.rb:11:in `<main>'
luna:~ %  

Java の場合と Ruby の場合の違い

ついでに Java の場合を見て見ます。Java の場合は少し違います。

Exception ex = new Exception("dummy");
ex.printStackTrace();

これだけです。例外を作るだけで良く、投げる必要はありません。

luna:~ % java test      
java.lang.Exception: dummy
        at test.sub(test.java:3)
        at test.main(test.java:7)
luna:~ % 

ちなみに、Ruby で投げずにやってみると以下のようになります。

e = StandardError.new('dummy')
puts e.backtrace.join("\n")
luna:~ % ruby test.rb
Traceback (most recent call last):
        1: from test.rb:8:in `<main>'
test.rb:5:in `main': undefined method `join' for nil:NilClass (NoMethodError)
luna:~ % 

backtrace がまだ nil なんですね。やはり投げる必要があるようです。

まとめ

今回は簡単に、Ruby と Java での backtrace 取得方法の違いをご紹介してみました。

IDE が便利なのだろうということは解っていますが、 私の手や頭が馴染む気がしないため、今だに Emacs を使いつつ printfデバッグを続けています。 しかも TAGS すら使わず、grep です。 この辺はもう老害と言われても仕方ないですね。

ではまた!