想定外の現象 : 論理エラーの検出
更新 : 2007 年 11 月
このレッスンでは、プログラム内の論理エラーを検出する方法について説明します。
前のレッスンでは、コンパイラ エラーおよびランタイム エラーを検出して修正する方法について説明しました。3 種類目のプログラミング エラーは、論理エラーで、検出が最も困難なエラーです。論理エラーの場合、警告は一切出ません。プログラムは動作しますが、結果は間違っています。それからコードを精査して、問題が発生した理由を調べる必要があります。
これには、Visual Basic のデバッグ ツールが役立ちます。ブレークポイントの設定とコードのステップ実行の 2 つのデバッグ手法により、実行中にコードを 1 行ずつ調べて、エラーを検出できます。
実行できるコード行いずれに対しても、コード エディタでブレークポイントを設定できます。プログラムを実行してブレークポイントのコード行に達すると、実行が強制的に停止され、中断モードに入ります。そして、その時点でのプログラムの状態について、必要な情報を取得できます。変数の値を確認したり、[イミディエイト] ウィンドウで式をテストしたり、エディット コンティニュを使用してコードを変更したりできます。
中断モードに入ると、コードをステップ実行、つまり 1 行ずつ実行して、コードがどのように動作するかを確認できます。F8 キーを押すと、現在のコード行が実行され、次の行で停止します。その時点で、変数の値を調べて、次の行に移動する間に値がどのように変化するかを確認できます。
現在のコード行が、コード内の他の場所の関数または Sub プロシージャを呼び出している場合、F8 キーを押すと、実行はそのプロシージャにステップ インします。プロシージャのステップ実行が終わると、そのプロシージャを呼び出した行の次の行に戻ります。プロシージャをステップ実行しない場合は、Shift キーを押しながら F8 キーを押して、プロシージャをステップ オーバーします。
やってみよう
論理エラーを検証するには
[ファイル] メニューの [新規作成] をポイントし、[プロジェクト] をクリックします。
[新しいプロジェクト] ダイアログ ボックスの [テンプレート] ペインで、[Windows アプリケーション] をクリックします。
[プロジェクト名] ボックスに「LogicErrors」と入力し、[OK] をクリックします。
新しい Windows フォーム プロジェクトが開きます。
ツールボックスから、フォームに 2 つの TextBox コントロールと 1 つの Button コントロールをドラッグします。
Button1 をダブルクリックしてコード エディタを開きます。
Button1_Click イベント ハンドラに次のコードを追加します。
Dim minutes As Integer = CInt(Textbox1.Text) Dim miles As Double = CDbl(Textbox2.Text) Dim hours As Double = 0 hours = minutes / 60 MsgBox("Average speed " & GetMPH(hours, miles))
End Sub 行の下に次の関数を追加します。
Function GetMPH(ByVal miles As Double, ByVal hours As Double) _ As String GetMPH = CStr(miles / hours) End Function
F5 キーを押してプログラムを実行します。最初のテキスト ボックスに「10」(10 分を表す) と入力し、2 番目のテキスト ボックスに「5」(5 マイルを表す) と入力して、Button1 をクリックします。
メッセージ ボックスに "Average speed 0.03333334" というメッセージが表示されます。しかし、5 マイルを 10 分で移動する場合、正しい答えは 30 mph です。
プロジェクトは開いたままにしておいてください。次の手順で、論理エラーを検出する方法について説明します。
論理エラーの検出
前の例では、プログラムのロジックに明白な間違いがあります。1 時間あたり 30 マイル移動したはずが、この結果では、1 時間あたり 1 マイル未満しか移動していないことになります。どこにエラーがあるのでしょうか。
次の手順では、ブレークポイントを設定してコードをステップ実行し、エラーを検出します。
やってみよう
ブレークポイントを設定してコードをステップ実行するには
コード エディタで行 hours = minutes / 60 を探し、そのコード行の左マージンをクリックします。
マージンに赤い点が表示され、コードが赤で強調表示されます。これはブレークポイントを示します。
F5 キーを押して再度プログラムを実行します。最初のテキスト ボックスに「10」、2 番目のテキスト ボックスに「5」と入力します。次に Button1 をクリックします。
ブレークポイントに達すると、プログラムが停止します。行 hours = minutes / 60 が黄色で強調表示されます。
変数の値の上にマウスを置いて、値を調べます。hours の値は 0、minutes の値は 10 になります。
F8 キーを押して行 hours = minutes / 60 を実行し、次の行に進みます。
行 MsgBox("Average speed " & GetMPH(hours, miles)) の変数の値を調べます。hours の値は 0.166666672、miles の値は 5.0 になります。
F8 キーを再度押して、現在の行を実行します。
実行が行 Function GetMPH に進みます。
この行で変数の値を調べます。前の行とは逆に、miles の値が 0.166666672 になり、hours の値が 5.0 になっています。エラーが検出されました。
プロジェクトは開いたままにしておいてください。次の手順で、論理エラーを修正する方法について説明します。
論理エラーの修正
前の手順では、変数 miles と hours の値の位置が入れ替わっていました。原因がわかりますか。
行 MsgBox("Average speed " & GetMPH(hours, miles)) を見ると、GetMPH 関数に 2 つの引数 hours および miles がこの順序で渡されています。関数宣言 Function GetMPH(ByVal miles As Double, ByVal hours As Double)... を見ると、引数は miles、hours の順になっています。
引数が間違った順序で渡されたため、論理エラーが発生し、間違った計算が行われました。引数の型が異なっていれば、ランタイム エラーが発生したと思われますが、引数の型が同じだっため、ランタイム エラーは発生しませんでした。単純な間違いでしたが、その結果発生したバグは、検出するのが困難でした。
次の手順では、ブレークポイントを設定してコードをステップ実行し、エラーを検出します。
やってみよう
論理エラーを修正するには
コード エディタで、行 MsgBox("Average speed " & GetMPH(hours, miles)) を次のように変更します。
MsgBox("Average speed " & GetMPH(miles, hours))
左マージンの赤い点をクリックして、ブレークポイントを解除します。
F5 キーを押してプログラムを実行します。最初のテキスト ボックスに「10」、2 番目のテキスト ボックスに「5」と入力します。次に Button1 をクリックします。
今度は、正しい結果である "Average speed 30" を表示するメッセージ ボックスが表示されます。
プログラムは修正されたように見えますが、検出がさらに困難な論理エラーが存在します。この論理エラーの検出を試みる場合は、プロジェクトを開いたままにしておいてください。レッスン「別のバグ : 他のエラーを発見する」でプロジェクトを再び使用します。
次の手順
このレッスンでは、論理エラーを検出して修正する方法について説明しました。ここで、コメントの使用に関する次のレッスンに進むか、「別のバグ : 他のエラーを発見する」で別の論理エラーを検出してみるかを選択できます。
次のレッスン : 「プログラムの注釈 : コメントを使用する」