新人技術者のためのロジカル・シンキング入門(1) ―― いかにしてバグの原因を突き止めるか
【3】YESかNOかで答えが出る設問を積み重ねる
全体像が明らかになったら,次に事象の絞り込みに移ります.ここでのポイントは,「"YES"か"NO"かで答えが出る設問を積む」ということです(図5).言い換えると,客観的な証拠を積み重ねて事象を絞り込むようにすること,だれが見ても原因箇所が狭まっていくとわかるように切り分けを進めるということです.
図5 切り分けはYES/NOを客観的に判別できるように絞り込む
まず,"YES"か"NO"かで答えが出る設問を立て,問題のシステムを実際に動かしてその答えがどちらに導かれるかを確かめていく.それらの問いが図のようなロジカル・ツリーに従って頭の中にスムーズに描けると,事象がおのずと絞り込める.
前述のメモリ・リークの例で考えてみましょう.例えば,ソース・レビューを行った結果,「ソース中のmemset,memcpyはすべて転送サイズが正しかった」ことが確認できたとします.これで「メモリ・リークはない」と断言できるでしょうか? メモリ・リークはmallocのサイズをまちがえたときにも起こるし,引き数にとる構造体の型が関数間で不整合を起こしていた場合(例えば,ソースの版数管理を誤ったとき)などでも起こりえます.「memset,memcpyは正しい」とだけわかっても,「ハングアップは起こらない」というところまで事象を絞り込むことはできません.
● 客観的な設問を考えてみる
しかし例えば,「認証モジュールをダミー・ルーチンに変えたらどうなるのか?」と考えるようにしたらどうでしょう(図6).この設問は答えが"YES"か"NO"かで客観的に導かれるものです.ダミー・ルーチンに変えてもハングアップが直らないという結果が導かれれば,少なくとも認証モジュールは犯人リストから外せそうです.
図6 良い設問の例
認証モジュールをダミー・ルーチンに変え,ハングアップの犯人がこのルーチンかどうかを確認する.「ダミー・ルーチンに変えたらどうなるか?」というのは客観的な設問の一例となる.もちろん,このようなデバッグ・コードそのものにミスがあったら手戻りが発生するので,注意しながら進めること.
認証ブロックがなくなると待ち時間の整合がとれなくてシステムが正しく動かないのなら,十分に処理時間をかせげる空ループを埋め込むなどという補完手段があるでしょう.空ループが問題発生時以外のほかのデータでシステムを止めないのであれば,問題発生時の入力データでも同様に問題がないといえるからです.
この設問は,逆に「ハングアップが起こらなくなった」という場合でも同じように切り分けを進められます.なぜなら,認証モジュールがないとハングアップがなくなってしまうのであれば,このブロックが犯人である疑いが濃厚となるからです.
客観的な設問をきちんと立てることができれば,最初からメモリ・リークをにらんで怪しいソース記述を見つけられず行き詰まってしまうような場合より,ずっとスムーズに問題の切り分けを進められます.