バグの原因は、「バッファオーバーランによるメモリ破壊」です※2)。以下、詳細を解説します。
※2)バッファオーバーランは、確保しているデータ領域を超えて、隣接するデータ領域を書き換えてしまうバグです。バッファオーバーフローとか、「爆撃」とも呼びます。
本プログラムは、「examdata.txt」をカンマ区切りで読み出し、コンソールに表示するプログラムです。「YAMADA YUYA」と「YAMAMOTO AOI」の理科(science)のデータが正しく表示できていません。正しく表示できない原因は、ソースコードの以下の部分です。
//生徒の名前を取得する strcpy(name[no],token);
strcpy関数は、nameにtokenの文字列をコピーする関数です。名前の変数は、name[N][15]」と宣言してあります。つまり、名前は14文字までしか入力できません。3人目のデータ「WATANABE SHUICHIRO」は、18文字あり、strcpy関数を使用してしまうと、領域外の場所にデータを上書きする可能性があります。今回の場合は、メモリ上にnameの次のアドレスに理科のデータ(science)が入っており、その部分まで上書きしています。つまり、メモリ内は以下の表1のようになっており、理科のデータが壊れています※3)。
※3)今回の問題は、お手持ちの環境によっては動作が一致しない可能性があります。今回は、CygwinのGCC 7.3.0を使用しています。
1人目の「YAMADA YUYA」の理科の点数が70ではなく、79となっているのは、3人目のデータのアルファベットの「O」をコピーしているためです。コンソールへの表示は、10進数表記ですから、アルファベットの「O」は、ASCIIコードで「4F」で、「4F」を10進に変換すると「79」になります。
2人目の「YAMAMOTO AOI」の理科の点数が0となっているのは、3人目のデータの末尾「'\0'」が入っているためです。「\0」は、ASCIIコードで0を表すので、コンソールには数字の「0」が出ます。
このバグのトリッキーなところは、生徒の名前が「渡辺一郎」なら正常に表示し、「渡辺秀一郎」なら表示不正になる点です。最初の動作確認テストで、「渡辺一郎」をテストデータにしていれば「たまたま」正常動作し、プログラム作成者のAさんは「このプログラムでOK」と思ったはずです。で、実際のデータに「渡辺秀一郎」があると、メモリ破壊が発生し、渡辺秀一郎と関係がない生徒のデータが壊れます。この現象から「渡辺秀一郎のアルファベットの文字数が多いことが原因となり、他者のメモリを破壊した」とは思い付かないでしょう。OSのバグや、ハードウェアの不良まで疑い、Aさんは煮詰まってしまいます。
さらに、「渡辺太一郎(ワタナベタイチロウ)」と「渡辺秀一郎」の場合では、データの壊れ方が異なりますし、テストで「松本明子(マツモトアキコ)」を使い、実際のデータに「松本吉彦(マツモトヨシヒコ)」が入っている場合、「2人の名前の漢字の文字数は同じで、性別が違う」とミスリードの要素が増え、「名前のアルファベットの文字数が多く、バッファを破壊した」という原因特定に至りません。バグと無関係の場所に異常現象が現れるバグは、タチが悪く、原因究明に時間がかかります※4)。
上記のバグを引き起こさないためには、「配列nameの領域を増やす」「領域内までしかコピーしない」などの対策をせねばなりません。strcpy関数の使用方法を誤るとバグにつながるので、注意が必要です。
※4)連載「山浦恒央の”くみこみ”な話」の第64回、「クイズ!! バグはどこだ? 〜ちょっと休憩して、バグ探しに挑戦〜」では、ミスリードが非常に多く、バグの解決に時間がかかったケースとして、筆者の体験談を取り上げました。
今回の自己採点シートを以下に示します。
問題 | 内容 | 配点(点) |
---|---|---|
テストデータ表示プログラム | 問題文を一通り読んだ | 50 |
バッファオーバーランのバグであると推察できた | 50 | |
リスト6 自己採点シート |
今回は、バッファオーバーランのバグを仕込んだ、テストデータ表示プログラムを出題しました。皆さんは、バグを見つけることができたでしょうか。バッファオーバーランは、関係のない場所に異常が現れる「タチの悪いバグ」だと思います。筆者も、プログラムが想定通りにいかないことがありました。「おかしいなぁ」と数時間悩み、あらゆる場所にprintf関数を仕掛け、バッファオーバーランを見つけた経験があります。
組み込みソフトの開発では、メモリ領域を参照したり、書き換えたりすることが多くあります。メモリの領域を誤って書き換えると、プログラムは通常では考えられない不可解な動作をします。筆者のように、煮詰まって苦労する前にバッファオーバーランを見つける嗅覚を備えていただければと思います。
東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)
Copyright © ITmedia, Inc. All Rights Reserved.