バグ検出ドリル(9)デバッグの基本的な心構えは「人を見たら泥棒と思え」山浦恒央の“くみこみ”な話(109)(4/4 ページ)

» 2018年08月21日 10時00分 公開
前のページへ 1|2|3|4       

4.解答

 今回のバグは、「フィールド(配列)の領域外を書き換えている」です。

 本問題は、10×10マスのフィールド上で、キーボードを入力しながら、ゴールを目指すものです。フィールドの各マス目の表現方法は、変数field[10][10]の中に、「0」、「1」、「2」、「3」をセットします。今回の問題では、10×10マスの移動、つまりfield[0][0]〜field[9][9]の添え字ならば、何も問題は起こりません。しかし、field[0][7]に移動し、「↑」キーを押すと、以下の画面が現れます(図2)。

図2 図2 実行結果

 図2は、field[0][7]にいるときに、「↑」キーを押した場合の実行結果です。これは、配列field[-1][7]という「迷路の領域外」にアクセスし、値を「2」に書き換えたため発生しました。このバグを防ぐには、配列field[0][7]の中身を「0」にせず、「1」か「3」にする必要があります。

 配列に関連するバグは、かなり多く発生します。例えば、以下のような場合です。

  • 配列の領域外にアクセスした。
  • 配列の領域外を書き換えた。
  • バッファーがオーバーフローを起こした。

 上記のようなバグが発生しないよう、注意深くプログラムを作成する必要があります。また、プログラム解析ツールやコンパイラのオプションを使って、問題がありそうな箇所をあらかじめあぶりだすことも有効です※1)。バグを見つけた場合、デバッガを活用し、変数の値を見ながら、ステップ実行すると原因究明が容易になります。

 また、使用するデータをミスなく入力することも大事です。例えば、次のケースが問題となり、注意が必要です。

  • データベースに入力するCSVファイルなどに間違いがあった※2)
  • プログラムの各種パラメータに間違った値を入力した※3)

※1)C言語には、Valgrindという動的解析ツールがあります。詳細は、本連載第98回『タダでソフト開発の生産性と品質を上げる方法(8):メモリリークを一瞬で見つける「Valgrind」(その1)』をご覧ください。

※2)筆者は、かつて小規模なショッピングサイトのシステム移行の手伝いをしたことがあります。新ソフトにするに当たって、顧客データと商品データを新しいデータ構造にマッチするように整形する必要がありました。一通り、Excelを使ってデータを整形し、データを入力しました。その後、顧客に確認をしたもらったところ、「あるはずのデータがない」「データにありえない値がある」とクレームが入りました。原因は、筆者のデータ編集ミスが原因でした。

※3)数値演算中心のソフトウェアの場合は、外部パラメータのバグに悩むことがあります。例えば、電気、物理の計算で使う係数値は、通常のプログラマーには判別困難です。

5.自己採点シート

 ここまで読んで、一回も「???」とならなかった方は、マイナス20点です。上記で示した解決策、すなわち、「配列field[0][7]の中身を『0』にせず、『1』か『3』にする」は、ロジックではなく、データを変更して、領域外アクセスを防止しています。表面的にはこれで解決しますが、良い子はこんな修正をしてはいけません。きちんとロジックを修正しましょう。

 今回の迷路のデータを見ると、[0,7]以外は、フェンスで囲み、進行不可に設定してあります。設計者の意図が、「迷路は『1』で囲んであるため、領域外アクセスは起きない」であれば、その旨を仕様書に記述しなければなりません。その場合、迷路データにバグがあることになります。また、仕様書にそう記述してあっても、「迷路は必ず『1』で囲ってある」と信じてはいけません。データにエラーがあり座標が領域外をアクセスする場合を考慮し、「塀の外へ行く矢印記号を無効にする」及び「最初に、迷路が『1』で囲まれていることをチェックする」必要があります。

 「解答」が正しいとは限りません。自分の論理的思考に照らし、あらゆる場所に潜んでいるバグを見つけましょう。

 今回の自己採点シートを下記に示します。

問題 内容 配点(点)
迷路探索プログラム 問題文を一通り読んだ 20
ソースコードを一通り読んだ 20
デバッグをした 20
配列の領域外にアクセスするバグを発見した 20
バグを修正する場合、データの修正ではなく、ロジックの修正をした 20
その他のバグを見つけた 5×件数
リスト3 自己採点シート

6.終わりに

 今回は、迷路探索プログラムのバグを探す問題を出題しました。いつもより量はありましたが、バグを見つけることはできたでしょうか。また、「解答」にだまされなかったでしょうか。

 配列の領域外アクセスや書き換えは、不可解なバグの原因となります。また、データ定義のバグも、頭を悩ませる原因の1つです。このようなバグを作り込まないように注意したいですね。

 過去の記事でも同じことですが、筆者が想定できていないバグも残っていると思われます。「このプログラムには必ずバグがある。バグを見つける!」との意気込みで見ていただけると、意外なバグを見つけられるでしょう。

【 筆者紹介 】
山浦 恒央(やまうら つねお)

東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)


1977年、日立ソフトウェアエンジニアリングに入社、2006年より、東海大学情報理工学部ソフトウェア開発工学科助教授、2007年より、同大学大学院組込み技術研究科准教授、2016年より非常勤講師。

主な著書・訳書は、「Advances in Computers」 (Academic Press社、共著)、「ピープルウエア 第2版」「ソフトウェアテスト技法」「実践的プログラムテスト入門」「デスマーチ 第2版」「ソフトウエア開発プロフェッショナル」(以上、日経BP社、共訳)、「ソフトウエア開発 55の真実と10のウソ」「初めて学ぶソフトウエアメトリクス」(以上、日経BP社、翻訳)。


前のページへ 1|2|3|4       

Copyright © ITmedia, Inc. All Rights Reserved.