基礎から学ぶC#入門 90日コース | 実践力を高める - Day 61:デバッグ

Web APP 90日で身につけるC#
スポンサーリンク
スポンサーリンク

Day 61 のゴールと全体像

Day 61 では、いよいよ「デバッグ」という、実践力を一気に底上げしてくれるテーマに踏み込んでいきます。 コードを書く力ももちろん大事ですが、「バグを見つけて直す力」こそが、現場で頼られるエンジニアの武器になります。

今日のキーワードは次の4つです。

  • ブレークポイント
  • ステップ実行
  • 変数確認
  • コールスタック

どれも Visual Studio などの統合開発環境(IDE)でよく使う機能で、 「なんだか難しそう…」と感じる方もいるかもしれませんが、 一度“使い方の筋道”が見えてくると、むしろ手放せない相棒になってくれます。

ここでは、初心者の方でもイメージしやすいように、 小さなサンプルコードを題材にしながら、 デバッグの流れをステップバイステップで追いかけていきます。

デバッグの全体イメージをつかむ

デバッグって何をする時間?

デバッグは、ざっくり言うと次のような時間です。

  • コードが「どんな順番で」動いているかを観察する
  • 変数に「どんな値」が入っているかを確認する
  • 想定と違う動きをしている箇所を特定する
  • 原因を見つけて、修正する

つまり、プログラムの中で起きていることを“見える化”する作業と言ってもいいです。

そのための道具が、

  • ブレークポイント
  • ステップ実行
  • 変数確認
  • コールスタック

という4つの機能です。 これらを組み合わせることで、 「プログラムの中をゆっくり歩きながら、様子を観察する」ことができるようになります。

例題コード:ちょっとバグのある合計計算

まずは、デバッグの練習台になる小さなコードを用意します。

using System;

class Program
{
    static void Main()
    {
        int[] numbers = { 1, 2, 3, 4, 5 };

        int total = CalculateTotal(numbers);

        Console.WriteLine($"合計は {total} です。");
    }

    static int CalculateTotal(int[] values)
    {
        int sum = 0;

        // わざとバグを仕込んでみます(最後の要素を足し忘れている)
        for (int i = 0; i < values.Length - 1; i++)
        {
            sum += values[i];
        }

        return sum;
    }
}
C#

このコードは、

  • numbers{1, 2, 3, 4, 5} を入れて
  • CalculateTotal で合計を計算し
  • 結果を表示する

というシンプルなものです。

しかし、for 文の条件が i < values.Length - 1 になっているため、 最後の要素(5)が合計に含まれないというバグがあります。

実行すると、

合計は 10 です。

と表示されてしまい、本来の合計 15 と違う結果になります。 この「どこかおかしいぞ?」という状態を、デバッグで追いかけていきます。

ブレークポイント ― プログラムを一時停止させる

ブレークポイントとは

ブレークポイントは、

「ここで一度止まってね」とプログラムに指示するための印

です。

Visual Studio では、

  • コードの左側の余白(行番号の近く)をクリックすると
  • 赤い丸が付き、その行にブレークポイントが設定されます

プログラムを「デバッグ実行」すると、 その行に到達したタイミングで、プログラムが一時停止します。

どこにブレークポイントを置くとよいか

今回の例では、バグがありそうなのは CalculateTotal の中です。 なので、まずはこのメソッドの先頭にブレークポイントを置いてみます。

static int CalculateTotal(int[] values)
{
    int sum = 0;  // ← この行にブレークポイントを置く
C#

こうしておくと、

  • Main から CalculateTotal(numbers) が呼ばれた瞬間
  • sum = 0; の行でプログラムが止まる

という状態になります。

ブレークポイントの役割の深掘り

ブレークポイントは、

  • 「怪しいと思う場所」
  • 「処理の入口」
  • 「ループの中」

などに置いて、 その行に到達したときの状態を観察するための“観測点”として使います。

闇雲にたくさん置くのではなく、 「ここで止まると、何が分かりそうか?」を意識して置くと、 デバッグがぐっとスムーズになります。

ステップ実行 ― 1行ずつゆっくり進める

ブレークポイントでプログラムを止めたら、 次は「ステップ実行」で、1行ずつゆっくり進めていきます。

ステップ実行の種類

代表的なステップ実行は次の3つです。

  • ステップオーバー(Step Over)
    • 現在の行を実行して、次の行に進む
    • メソッド呼び出しがあっても、その中には入らない
  • ステップイン(Step Into)
    • 現在の行を実行し、メソッド呼び出しがあればその中に入る
  • ステップアウト(Step Out)
    • 現在のメソッドの残りを一気に実行し、呼び出し元に戻る

Visual Studio では、

  • F10 → ステップオーバー
  • F11 → ステップイン

というキーがよく使われます(設定によって違う場合もあります)。

例題コードでステップ実行してみる

ブレークポイントで sum = 0; の行に止まった状態から、 ステップオーバーで進めてみます。

static int CalculateTotal(int[] values)
{
    int sum = 0;  // ここで停止中

    for (int i = 0; i < values.Length - 1; i++)
    {
        sum += values[i];
    }

    return sum;
}
C#
  1. sum = 0; の行で止まる
  2. ステップオーバーすると、sum0 が入る
  3. 次の行 for (int i = 0; i < values.Length - 1; i++) に移る
  4. さらにステップオーバーすると、ループの中に入る

ループの中では、

sum += values[i];
C#

の行で止まりながら、

  • i がいくつか
  • values[i] がいくつか
  • sum がいくつになったか

を、1回ずつ確認していくことができます。

ステップ実行の大事な感覚

ステップ実行は、

「プログラムの中を、1行ずつ歩いていく」

ようなイメージです。

  • どの行がいつ実行されているか
  • ループが何回回っているか
  • 条件分岐がどちらの道に進んでいるか

を、目で見て追いかけられるようになると、 「なんとなく動いている」から「ちゃんと理解して動かしている」に変わっていきます。

変数確認 ― 今この瞬間の中身を見る

ステップ実行をしているときに、 ぜひセットで使いたいのが「変数確認」です。

変数の中身を確認する方法

Visual Studio では、

  • 変数名の上にマウスカーソルを乗せると、 現在の値がポップアップで表示されます
  • 「ローカル」ウィンドウや「ウォッチ」ウィンドウに変数を追加して、 値の変化を追いかけることもできます

例題コードの CalculateTotal をステップ実行しながら、

  • i
  • values[i]
  • sum

の3つを確認してみると、 ループがどんなふうに動いているかが、はっきり見えてきます。

実際に追いかけてみるイメージ

values = {1, 2, 3, 4, 5} のとき、

  • 1回目のループ
    • i = 0
    • values[i] = 1
    • sum0 + 1 = 1
  • 2回目のループ
    • i = 1
    • values[i] = 2
    • sum1 + 2 = 3
  • 3回目のループ
    • i = 2
    • values[i] = 3
    • sum3 + 3 = 6
  • 4回目のループ
    • i = 3
    • values[i] = 4
    • sum6 + 4 = 10

ここで、

  • i < values.Length - 1i < 4

なので、i = 4 のループは実行されません。 つまり、values[4] = 5 が足されないまま、sum = 10 で終わってしまいます。

この「最後の要素が足されていない」という事実は、 変数確認をしながらステップ実行することで、はっきりと目に見える形で理解できます。

変数確認の重要ポイント

  • 「想定している値」と「実際に入っている値」が違うとき、 バグの手がかりになります。
  • ループや条件分岐の中で、変数がどう変化しているかを追いかけることで、 「どこからおかしくなっているか」が見えてきます。

変数確認は、 プログラムの“心の声”を聞くようなイメージで使ってみると、 少し楽しくなってきます。

コールスタック ― 「誰が誰を呼んだか」の履歴

最後に、少し概念的ですが、とても大事な「コールスタック」を見ていきます。

コールスタックとは

コールスタックは、

「今の行にたどり着くまでに、どのメソッドがどの順番で呼ばれてきたか」

を示してくれる“呼び出し履歴”のようなものです。

Visual Studio では、

  • デバッグ中に「コールスタック」ウィンドウを開くと
  • 上から順に「現在のメソッド → その呼び出し元 → さらにその呼び出し元…」 という形で表示されます

例題コードでのコールスタック

例題コードをデバッグしているとき、 CalculateTotal の中で止まっているとします。

そのときのコールスタックは、だいたいこんな感じになります。

  • CalculateTotal(int[] values)
  • Main()

これは、

  • 今は CalculateTotal の中にいて
  • その呼び出し元は Main である

ということを示しています。

もし、

  • MainProcessDataCalculateTotal

というように、メソッドが何段階もネストして呼ばれている場合、 コールスタックを見ることで、

  • 「今どの階層にいるのか」
  • 「どのメソッドからここに来たのか」

を把握することができます。

コールスタックが役立つ場面

  • 例外が発生したとき
    • 「どのメソッドで例外が起きたか」
    • 「そのメソッドはどこから呼ばれていたか」 を知る手がかりになります。
  • 複雑な処理の流れを追いたいとき
    • 「このメソッドは、どこから呼ばれているのか?」 を確認することで、全体像をつかみやすくなります。

コールスタックは、 プログラムの“足跡”をたどるための地図のような存在です。

バグを直してみる ― デバッグから修正へ

ここまでの流れで、

  • ブレークポイントで CalculateTotal の入口に止まり
  • ステップ実行でループを1回ずつ追いかけ
  • 変数確認で sumi の値を見て
  • 「最後の要素が足されていない」という事実に気づく

というところまで来ました。

では、実際にバグを直してみます。

修正前

for (int i = 0; i < values.Length - 1; i++)
{
    sum += values[i];
}
C#

修正後

for (int i = 0; i < values.Length; i++)
{
    sum += values[i];
}
C#

values.Length - 1values.Length に直すことで、 i0 から 4 まで回り、

  • 1 + 2 + 3 + 4 + 5 = 15

という正しい合計が求められるようになります。

修正後にもう一度デバッグして、

  • ステップ実行でループを追いかけ
  • 変数確認で sum の変化を見て

「今度はちゃんと最後の要素まで足されている」と確認できれば、 バグ修正完了です。

デバッグのミニテンプレート

最後に、デバッグの流れをざっくりテンプレートとしてまとめておきます。

  1. おかしい結果に気づく
    • 「想定していた値と違う」
    • 「例外が出る」
  2. 怪しい箇所にブレークポイントを置く
    • 計算処理の入口
    • ループの中
    • 条件分岐の前後
  3. ステップ実行で1行ずつ進める
    • ステップオーバーで流れを追う
    • 必要に応じてステップインでメソッドの中に入る
  4. 変数確認で中身を観察する
    • 「想定している値」と「実際の値」を比べる
    • ループ回数や条件分岐の道を確認する
  5. コールスタックで呼び出し関係を把握する
    • どのメソッドからここに来たかを確認する
  6. 原因を特定して、コードを修正する
    • 条件式のミス
    • ループ範囲のミス
    • 代入漏れ・初期化漏れ など
  7. もう一度デバッグして、直ったことを確認する

この流れに慣れてくると、 「バグが怖いもの」から「ちょっとしたパズル」くらいの感覚に変わっていきます。

Day 61 のまとめ

Day 61 では、

  • ブレークポイントで「ここで止まってね」とプログラムに指示し
  • ステップ実行で1行ずつゆっくり進めて
  • 変数確認で「今この瞬間の中身」を見て
  • コールスタックで「誰が誰を呼んだか」の履歴をたどる

という、デバッグの基本的な流れを学びました。

デバッグは、最初は少しとっつきにくく感じるかもしれませんが、 「プログラムの中を散歩する感覚」で触ってみると、だんだん楽しくなってきます。

ぜひ、

  • 自分のコードにわざと小さなバグを仕込んでみる
  • ブレークポイントとステップ実行で「どこがおかしいか」を探してみる
  • 変数確認とコールスタックを使って、プログラムの流れを眺めてみる

といった小さな練習を重ねながら、 「バグと仲良くなる」感覚を育てていっていただければうれしいです。

タイトルとURLをコピーしました