Rustプログラミングにおけるデバッグ入門

これはRust Language Advent Calendar 2014の第1日目となります。

尚、本情報はRust 0.13.0-nightly@fac5a0767時点の情報を基にしております。

現実においてプログラムを書くにあたりデバッグを行わないということはありません。ですので、通常、我々はデバッグ技法というものを習得しなければなりません。

デバッガ

RustではDWARF形式のデバッグシンボルを出力できるため

といったツールの使用が可能です。WinおよびLinuxではgdbを使えばいいでしょう。OSXでは、個人的にはlldbを使えばいいと思います(尚、gdb向けの拡張スクリプトもrustリポジトリの中には存在しています)

また、DWARF形式のシンボルを用いた各種ツールチェインも使用が可能となっていますが、各種バグには注意を配る必要があるかもしれません。

log crate

デバッガを用いずとも、変数の内容などをダンプするデバッグというのも非常に有用あるのは皆さんご存知のことと思います。殊、Rustのように平行・並列実行を指向したコードを記述する場合、デバッガでアタッチしたりrrのようなツールチェインを使わずとも済ませたい・もしくは前述のツールチェインを使いことが困難なこともあると思うので、この手法にはお世話にならざるを得ません。

そこで使うのがこの log crateです。 詳細な使い方はリンク先を参照していただくとして(安定度もexperimentalですしそちらの方が確実でしょう)、概要を説明しますと、

  1. log
  2. debug
  3. info
  4. warn
  5. error

のレベルに分けてログを出力することができます。

出力にあたっては、実行時にRUST_LOG=path::to::module=log_level環境変数を設定することで、「ログのレベル」と「ログを出力する対象であるモジュール」の指定が可能です。

この指定は、正規表現および用いた複雑な表現が可能であり、/の後にwarn/bar*fooのように続けることで「ログレベルwarn以上で、正規表現bar*fooにマッチするメッセージを含むログを出力する」などのような指定を環境変数経由で実行時に指定することが可能です。

また、原則としてmacroで実装されているので、現在の実装では、debug!に関しては--cfg ndebugコンパイルオプションとしてrustcに指定した場合に、自動で無効化されます.

アサーション

Rustには実行時アサーション複数デフォルトで存在しています.

debug_assert系では、--cfg ndebugrustcに対して渡すことにより、これらのアサーションを無効にしたコードの生成が行われます。

ユニットテストベンチマーク

Rustではコード中に#[test]または#[bench]といった指定を行ってコードを記述することで、コンパイルオプションによりユニットテストまたはマイクロベンチマーク用のバイナリを簡単に生成することが可能です。

詳しくはThe Rust Testing Guideを参照するのが良いでしょう。

バックトレース

実行時に環境変数としてRUST_BACKTRACE=1を設定することで、クラッシュ時の詳細なバックトレースを得ることができます。

cargo buildrustc —cfg ndebug相当のことをする

cargoの設定のprofileで明示的に指定を行えば、対応するビルドプロファイルに反映されます。

デフォルトでは--releaseをつけた場合にrustc —cfg ndebug相当となります

まとめ

よいRustプログラミングをお楽しみください. 明日の担当予定は@omasanoriさんです。