デバッグ機能の基本

デバッグとは

プログラミングは「こういう動作をして欲しい」とあらかじめ決めてから、その通りの動作をするようにコード記述していきます。
しかし時に期待通りに動作しないことがあります。
これはコードが間違っているということですが、コードのどの部分が間違っているのかが分からないということがあります。
数行程度のコードならばコードよく見直せば発見できるかもしれませんが、数十、数百行ものコードとなるとどこに間違いがあるのかを発見するのが大変です。

Visual Studioではこのようなコードの間違いを発見、修正するための機能があります。
これをデバッグ機能といいます。

以下はC#の説明というよりもVisual Studioの使い方の説明です。
Visual Studio以外でも開発環境を使用しているならデバッグ機能が搭載されていると思うので、各自で調べてください。

まれに、使用しているライブラリのバグで動作がおかしいということはあります。
しかし滅多にあることではないので、うまく動作しない場合はまずは自分で書いたコードの間違いを疑うべきです。
(.Net Framework標準のライブラリを使用しているならなおさら)

Visual Studioのデバッグ機能

以下の画像の青色部の面積をプログラミングで計算してみましょう。
(円は正円です)
デバッグのための例題

以下のようなコードを書いたとします。


static void Main(string[] args)
{
    //正方形の一片の長さ
    int side = 5; 

    //正方形の面積
    int areaSquare = side * side;

    //円の面積
    double areaCircle = (side / 2) * (side / 2) * 3.14;

    //青色部の面積
    double areaBlue = areaSquare - areaCircle;

    Console.WriteLine(areaBlue);
    Console.ReadLine();
}

まず正方形の面積を算出し、次に円の面積を算出します。
そして円の面積を正方形の面積から引けば答えになります。

このコードの計算結果は以下です。

12.44

さてこれは本当に正しいでしょうか?
電卓をたたいて計算してみると、正しくは「5.375」です。
パっと見ただけでも青色部分は正方形面積の半分よりもっと少ないですよね。

しかしコードを見直してみても何が間違いなのかがよくわかりません。
そんな時はデバッグ機能を使用すると間違いの発見が容易になります。

まず、Visual Studioのコードエディタ上で、間違いがありそうな行の左端のエリアをクリックします。
(画像のマウスポインタのあたり)
Visual Studioのデバッグ機能1

すると赤い丸印がつけられます。
この赤丸の点をブレークポイントといいます。
Visual Studioのデバッグ機能2

この状態でプログラムを実行します。
すると、ブレークポイントの行を実行する直前でプログラムの実行が停止します。
つまり、変数areaSquareには値はまだ何も入っていない状態です。
Visual Studioのデバッグ機能3

次に実行される行の左端には黄色い矢印が表示されます。
(この行はまだ実行されていません)

ブレークポイントで停止中は、Visual Studioの画面下部に「ローカル」というウィンドウが表示されます。
Visual Studioのデバッグ機能4

もし表示されていない場合は「デバッグ」メニュー→「ウィンドウ」→「ローカル」から表示してください。
Visual Studioのデバッグ機能5

この「ローカル」ウィンドウには現在実行中のコードにある変数とその中身の一覧が表示されます。

ブレークポイントで停止中は、「F10」キーでコードを一行ずつ実行可能です。
これをステップ実行といい、「F10」キーはステップオーバーという実行方法です。
「デバッグ」メニュー内からでも実行できますが、F10キーのほうが圧倒的に早いので覚えてしまいましょう。

試しに上記状態から一回だけF10キーを押してみます。
Visual Studioのデバッグ機能6

先ほどの「int areaSquare = side * side;」の行が実行され、変数areaSquareには計算結果が代入されます。
代入の結果はローカルウィンドウで確認できます。
(直前の実行で値が変化した変数は赤色で表示されます)

このように、コードを一行ずつ実行して変数の値の変化をチェックできるので、間違いを見つけるのに役立ちます。

ちなみにこのコードの間違いは円の面積の算出方法です。
そのままもう一度ステップ実行してみると、変数areaCircleには「12.56」が入ります。
正方形の面積の半分ほどしかありませんから、明らかに小さいですよね。
(実際に実行してみて確かめてみましょう)

円の面積を求める公式自体は間違っていないのですが、実は円の半径を求める段階で間違った値になっています。

int型は整数型を扱うデータ型で、小数は扱えません。
コード中に直接記述される整数(今回は「2」)は、特別な指定をしなければint型となります。
そして、int型同士の割り算の結果はint型になります。
これらの性質から、「5÷2」の計算結果は「2.5」ではなく、小数以下は切り捨てられて「2」になってしまうのです。

実際に以下のコードを書いて確かめてみましょう。
変数の値の確認は今まで通り「Console.WriteLine」で表示しても良いですが、デバッグ機能で停止して確認しても良いです。


int num = 5 / 2;		//←2

//演算の時点ですでにint型なので
//double型で受け取ってもダメ
double real = 5 / 2;	//←2

このあたりのことはデータ型で改めて解説するので、今はそんなに理解しなくても構いません。

コードの間違いを直したのが以下です。


static void Main(string[] args)
{
    //正方形の一片の長さ
    int side = 5; 

    //正方形の面積
    int areaSquare = side * side;

    //円の面積
    double areaCircle = (side / 2.0) * (side / 2.0) * 3.14;

    //青色部の面積
    double areaBlue = areaSquare - areaCircle;

    Console.WriteLine(areaBlue);
    Console.ReadLine();
}
5.375

コード中に直接記述する値を「2」から「2.0」に変更しただけです。
一見意味がないように思えますが、数値に小数点を記述するとその値はdouble型であるとみなされます。
これで「int型÷double型」の演算になり、計算結果はdouble型になるので、正しい結果が得られるようになります。

詳しくはリテラルの項で説明します。

ステップインとステップオーバー

デバッグの実行方法にはステップインステップオーバーの二種類があります。
これらはメソッドに関係するステップ実行機能なので、ステップインによるメソッド内部のデバッグで改めて解説します。