Julia で Valgrind を使う
Valgrind はメモリデバッグ・メモリリーク検出・プロファイルを行うツールです。この章では Valgrind を使って Julia のメモリ関連のバグをデバッグするときに気を付けるべき事項を紹介します。
一般的な注意点
初期設定の Valgrind はプログラムが自己改変を行わないと仮定します。この仮定は多くのプログラムで守られますが、julia
のような JIT コンパイラでは簡単に破られます。このため valgrind
には --smc-check=all-non-file
を必ず渡すようにしてください。これを忘れると、クラッシュや異常な振る舞いが (たいてい見つかりにくい形で) 引き起こされます。
Valgrind でメモリエラーを検出するときは、julia
のメモリプールを無効化した方が分かりやすい場合もあります。コンパイル時のフラグ MEMDEBUG
を付けると Julia でメモリプールが無効化され、MEMDEBUG2
を付けると femtolisp でメモリプールが無効化されます。この二つのフラグを付けて julia
をビルドするには Make.user
に次の一行を追加してください:
CFLAGS = -DMEMDEBUG -DMEMDEBUG2
もう一つ注意事項: プログラムが複数のワーカープロセスを使うときは、親プロセスだけではなくワーカープロセスも Valgrind に監視させたいはずです。valgrind
に --trace-children=yes
を渡すとこれを行えます。
警告を抑制する
通常 Valgrind は実行中に大量の警告を出力します。警告を減らすには、Valgrind に抑制ファイルを渡すとよいでしょう。抑制ファイルのサンプルは Julia ソースツリーの contrib/valgrind-julia.supp
にあります。このサンプル抑制ファイルをソースツリーのトップディレクトリから使うコマンドを示します:
$ valgrind --smc-check=all-non-file \
--suppressions=contrib/valgrind-julia.supp \
./julia progname.jl
出力されたエラーは全てバグとして報告されるか、抑制ファイルに追加されるべきです。なお一部のバージョンの Valgrind にはデフォルトの抑制処理にバグがあるので、バグを報告する前にこれを踏んでいないか確認するようにしてください。
Valgrind 内で Julia テストスイートを実行する
julia/test
ディレクトリで次のコマンドを実行すれば、Julia テストスイートを Valgrind 内で実行できます。通常は数時間単位の非常に長い時間がかかります:
valgrind --smc-check=all-non-file \
--trace-children=yes \
--suppressions=$PWD/../contrib/valgrind-julia.supp \
../julia runtests.jl \
all
"完全な" メモリリークの報告を見たいのであれば、valgrind
に --leak-check=full --show-leak-kinds=definite
フラグを渡してください。
注意点
現在の Valgrind は複数の丸めモードをサポートしません。そのため丸めモードの変更を含むコードを Valgrind 内で実行すると振る舞いが変化します。
一般に、もし Valgrind
に --smc-check=all-non-file
を設定したときにプログラムの振る舞いが変化した場合には、--tool=none
を付けてから調査を行うべきです。こうすると最小限の Valgrind が有効化されるので、メモリチェッカーを完全に有効化する場合より実行がずっと高速になります。