今回の解答を下記に示します。
計算結果が、int型の範囲を超える場合、オーバーフローとなります。筆者の環境は、Visual Studio 2010コンソールアプリケーションで作成しており、int型のとり得る範囲は、下記となります。
最小値 | 最大値 | |
---|---|---|
int型 | -2147483648 | 2147483647 |
「電卓プログラム」の加算と乗算を実行し、上記の最大値や最小値を超えると、オーバーフローします※1)。
オーバーフローのバグは、常習的なバグとして昔から有名で、これを防ぐには、最大値が入力されても溢れない十分な大きさの変数を確保するとか、入力しないよう使い方に制限をかける必要があります※2)。
※1)この1行を読んで、「オーバーフローは加算と乗算だけじゃないだろ」と思った方は正解です。オーバーフローは、加算、乗算だけでなく、減算、除算でも発生します。-2147483648(最小値)を「-1」で除算すると、2147483648となり、最大値を越えます。また、-2147483648(最小値)から「1」を減じても、オーバーフローします。
※2)今回の問題では、scanfを使っています。この標準関数は、大半の学生プログラムで慣習的に使いますが、異常処理を回避するのが非常に難しい関数として有名です。ある意味、くせ者関数ですね。例えば、本問題で文字などの異常値を入力すると、ハングアップします。大学の教員の中には、「scanfを学生に教えるな」と言う人もいます。
2つ目の入力値に0をセットするとゼロ除算が発生し、本プログラムはフリーズします。ゼロ除算は、0による除算を実施することで発生するバグです。これも古典的で常習的な「あるあるバグ」で、今まで多くのソフトウェアで甚大な被害を与えてきました。この問題を解決するには、0の時は、計算しないなどの工夫が必要です。例えば、Windowsの標準ツールの「電卓」アプリで、「4 / 0」を入力すると、「0で割ることが出来ません」と表示が出ます。
「電卓プログラム」の場合は、ゼロ除算で大きな影響が出ることはありませんが、ミッション・クリティカルなプログラムでは、重大事故に直結します。ソフトウェアの中に割り算処理があれば、ゼロ除算が起きないガードがあるか、十分注意しましょう。
問題 | 内容 | 配点(点) |
---|---|---|
電卓プログラムの問題 | 5分以上考えた | 50 |
加算、乗算でオーバーフローの可能性を見つけた | 15 | |
減算、除算でオーバーフローの可能性を見つけた | 10 | |
ゼロ除算の可能性を見つけた | 25 | |
上記以外のバグを見つけた | +α | |
リスト6 自己採点シート |
短いプログラムでも、バグなしで作るのは簡単ではありません。今回は、学生が数分で書ける電卓プログラムを出題しました。小さいプログラムでも、異常処理を考えると、いろいろなことを考慮せねばなりません。
オーバーフローやゼロ除算は、昔から有名な常習的バグです。仕様の段階からしっかりとレビューして見つけるか、テスト工程で同値分割を適用し、確実に摘出できるようにしましょう。
今までの問題もそうですが、筆者が想定していないバグや考え違いもあるでしょう。それも合わせて見つけていただければと思います。
東海大学 大学院 組込み技術研究科 非常勤講師(工学博士)
Copyright © ITmedia, Inc. All Rights Reserved.