再現が難しいバグは、開発者にとって悩ましい課題の一つです。
発生頻度が少ない場合は後回しにされることもよく見る光景ですが、開発終盤になればなるほど根本原因の修正が難しくなるもの・・・。
では、と重い腰を上げて解決に乗り出すも、不具合の原因に当てもない場合、従来のデバッガを使ってブレークをかける手法やprint文を使った手法では手間がかかりすぎてしまっていつの間にか工数が増大・・・なんてことも。

そこで、本記事では実動作の挙動を丸ごとトレースして、再現が難しい不具合の原因をすばやく特定して工数を短縮する手法に焦点を当てます。

CONTENTS
  1. 一般的な不具合解析の手法
  2. 再現が難しい不具合の原因捜査が難しいワケ
  3. 動的解析ツールの有効性
  4. まとめ
 

一般的な不具合解析の手法

開発現場のエンジニアが不具合解析を行う際の代表的な手法を次に挙げます。
みなさんは普段どのような手法を使っていますか?

1. デバッガを使った手法

ICE(インサーキットエミュレータ)やJTAGエミュレータなどのデバッガを使ってブレークポイントを設定し、プログラムの特定のポイントで処理を停止してステップ実行させたり、変数の値を確認したりする手法です。

ただし、すべての処理がブレークポイントで止まるわけではないため、プログラムを熟知していない場合や、原因に当たりがついていない場合では、不具合の特定が困難になります。
また、プログラムの実行を止められない機器や問題では使用することができません。

2. オシロスコープを使った手法

デバッグ用のポートをHi/Loさせる処理をソースコードに追加し、オシロスコープを使って状態を観測する手法です。
組込み開発で使われる手法で、ソースコードに与える影響(実行時間)が大変少ないため、特にタイミングや信号の波形を確認する場合に有用です。

しかし、一度に確認できる範囲が極めて限定的で、変数値の確認も困難なため、ソフトウェアのロジックエラーやメモリ関連の問題には対処しにくい手法となります。

3. print文を使った手法

コード内にprint文を挿入し、プログラムの実行時に特定の変数の値やメッセージを、シリアル通信を介してコンソールに出力させる方法です。
開発言語によってはprintfデバッグ、printkデバッグなどと呼ばれることもあります。比較的手軽に利用でき、リアルタイムでの情報収集が可能です。

しかし、多用すると
・ソースコードの可読性が低下する
・埋め込んだprint文の管理が難しくなる
・不要なログが出力されて必要な情報が見つからなくなる
・実機動作のタイミングが大きく変わってしまう
など、かえってデバッグの複雑さが増してしまいます。

 

再現が難しい不具合の原因捜査が難しいワケ

続いて、再現が難しい不具合にはどのようなものがあるでしょうか?

  • ・発生するまで時間がかかる
  • ・タイミングや条件がシビア
  • ・機器を止めることができない
  • ・そもそも発生させる手順が確立していない


このような不具合では、
発生した瞬間およびその前後プログラムの実行経路や変数の情報を、
いかにキャッチすることができるか?
が重要になります。

先に述べた手法の中では、print文を活用してログ解析する方法がシンプルで迅速にデバッグを開始でき、かつ機器を止めずに済むため有効です。具体的には次のような手法でログを取得します。

  1. 状態の出力
    問題の発生に関係がありそうな関数の出入り口の通過情報をprint文で出力する。
    変数やオブジェクトの状態をprint文で出力する。
    ※当たりがついていない状態なので広めに取得する。

  2. 条件分岐の出力
    1の関数の条件分岐についてどこを通過したかをprint文で出力する。

  3. エラーの出力
    例外や問題のある個所を通過した際にエラー情報を出力する。

ただし、前述した内容ともかぶりますが、print文デバッグでは再現しにくい不具合の解析が難しい部分も存在します。

  • 情報の過不足
    なかなか一度の再現で必要な情報を得ることは難しく、当てが外れた場合や更に原因箇所を絞り込んで特定したい場合は、print文を挿入する箇所を変更してログを再度取得しなければならないため、必然と試行回数は多くなり、それに比例して再現確認の工数も膨らんでしまいます。
    一方で過剰に情報を出力すると、ログを分析するのに大変な手間がかかることになります。

  • 動作への影響
    余計な処理が入ることになるので、処理のタイミングが変わって不具合自体が発生しにくくなることも実際にはあります。
    そのような場合には通常print文の量を減らして調整します。
    全く発生しなくなってしまう場合は別の手法を検討する必要があります。
 

動的テストツールの有効性

再現しにくい不具合の原因捜査で工数が膨らまないようにするには、先に述べた通り
発生した瞬間およびその前後プログラムの実行経路や変数の情報
さらに、少ない試行回数大量に取得しなければなりません。

そこで登場するのが一般的に「動的テストツール」と呼ばれているログ解析のツールです。
「動的テストツール」のしくみはprint文のログ解析と似ていますが、次の面で優れています。

  • ・埋め込んだログ出力用コードの管理機能があり、一括で挿入/削除などができる
  • ・ソースコードの可読性を損なわないエディタやソースコードビューが用意されている
  • ・一回トレースログを取得するだけで、広範囲なプログラムの経路や変数値、
     処理時間や割り込みのタイミングまで記録・分析できる
  • ・記録されたログを遡ってバックトレースができる
  • ・グラフィカルな解析用のGUIが多数用意されておりプログラムの経路や変数値を解析しやすい
  • ・実機動作に与える影響がprint文より少ないものもある
  • ・ツールによっては数秒~最大1か月間の長時間トレースが可能

このように、「動的テストツール」を用いることで、再現が難しい不具合の原因を確実に把握することができます。
また、修正後の確認をする場面でも、内部の挙動を確認して試行回数を最低限に抑えることができます。

弊社動的テスト「DT+(ディーティープラス)」を導入した事例では、最大75%の大幅な工数短縮が実現しています。

動的テストツールDT+による実行経路・変数値のトレース

変数値のグラフ表示

関数遷移のグラフ表示

なお、動的テストツールであっても、print文と同様に、ログ出力コードを挿入すると不具合が再現しなくなってしまうような問題の場合はバグ解析不可能であり、避けられないことでもあります。
もし余計な負荷がかからないような解析手法が他にあるのであればそちらを使うべきですが、無いのであればprint文やオシロを使って解析するより動的テストツールを使う方が、何十倍何百倍もマシだと考えております。

 

まとめ

いかがだったでしょうか。
なかなか再現しないバグに悩まされたことがある方は少なくないと思います。デバッガやprint文を駆使しても解決できない場合は動的テストツールも視野に入れてみてはいかがでしょうか。お気軽に無料トライアルでお試しください。

 


【 無料でみれる! 】
動的テストツールDT+ デモ動画

ソフトウェア開発者のための動的テストツール「DT+」をご紹介する動画です。
ソースコードの実行によりログを収集し、多彩な解析機能によりソフトウェアの動作をこまかく見える化。たった数クリックの解析で、関数遷移や変数の変動、カバレッジをグラフィカルに表示します。本動画では、そんなDT+の導入手法から実際の解析の様子まで、基本的な使い方をデモンストレーションいたします。

お申し込みはこちら!