C#入門編

C#入門編 Visual Studio 2022 デバッガの基本① ~ブレークポイントとステップ実行~【初心者でも効率的なデバッグ!】

今回はプログラミングにおける強力な武器となる「デバッガ」について解説します。

Visual Studioのデバッガ機能を使いこなせるようになると、プログラムの動作を詳細に把握でき、問題解決が格段に効率化します。

この記事では以下について説明します。

  • デバッグとは何か?その重要性
  • ブレークポイントの設定と活用方法
  • ステップ実行でプログラムの流れを理解する方法
  • 変数値の基本的な確認方法
  • メソッド呼び出し履歴について

以下のような方に役立つ内容となっています。

  • プログラミング初心者の方、特にC#開発を始めたばかりの方
  • Visual Studioのデバッグ機能をまだ使いこなせていないと感じる方
  • プログラムのバグを効率よく解決したいと考えている方
プロ太

デバッガは「エラーの原因がわからない」「想定と違う動作をする」と問題解決において欠かせない道具です!

加えて、プログラミング学習において、プログラムの動作を理解する上でも役立つでしょう。

C#プログラミングの基本の学習についてはC#入門編シリーズをぜひ見てください。

C#入門編(1)Visual Studioで開発 ~HTMLでHello World~ このC#入門編では、HTMLファイルの生成を題材として、C#の基本的な機能について学んでいきます。 YouTubeの動画でも解説...

Visual Studioの基本については以下の記事でまとめていますので、こちらもぜひ参考にしてください。

C#入門編 Visual Studio 2022 初心者向けガイド ~基本から応用まで~ 今回はプログラミングにおける強力な味方であるVisual Studioについて解説します。 この記事では以下について説明します。...

YouTube動画も作成しています。

デバッグとは?

プログラムを開発する際、大きく分けて(A),(B),(C)3種類のエラー(誤り)が発生します。

  • (A)ビルドエラー(コンパイルエラー):プログラムをビルド(コンパイル)する段階で発生するエラー。
  • (B)実行時エラー: プログラムの実行中に発生するエラー
    (例)プログラムが実行中に配列の範囲外にアクセスしようとして「インデックスが範囲外です」という例外が発生する。
  • (C)論理エラー: プログラムは動くが、期待した結果にならない
    (例)気温を摂氏から華氏に変換する計算式を間違えたため、プログラムは動くが出力される温度の値が正しくない。

デバッグはアプリ実行中のエラーの原因を特定して修正するプロセスであり、「(B)実行時エラー」や、「(C)論理エラー」の解決が目的となります。

Visual Studioのデバッガはこのようなエラー原因の特定を強力に支援してくるツールです。

プロ太

それでは、実際にC#コンソールアプリのプロジェクトを作成し、Visual Studioデバッガの機能について一緒にみていきましょう!

デバッグモードとリリースモード

Visual StudioでC#コンソールアプリの新規プロジェクトを作ります。

今回、デバッグ時の説明をわかりやすくするため、以下のように最上位レベルのステートメントを使用せず、ProgramクラスとMainメソッドを明示的に作成します。

Visual Studioには「デバッグモード(Debug)」と「リリースモード(Release)」という2つのビルドモードがあります。

Visual Studioのデバッガを使う場合には、デバッグモードでビルドする必要があります。

デバッグモードのビルドは、コードの実行速度より「デバッグしやすさ」を優先しているため、デバッグ用の様々な情報を含んだ実行ファイルが作られます。

プロ太

開発中はデバッグモード、完成したらリリースモードで配布するのが基本ですね。

メニューバーで「ツール>オプション>テキストエディター>C#>全般」で「行番号」にチェックを入れると、エディタで行番号が表示されるようになります。

ブレークポイント

ブレークポイントとは、プログラムの実行を特定の行で一時停止させるための目印です。実行が停止することで、その時点でのプログラムの状態(変数の値など)を確認できます。

プロ美

つまり、プログラムの実行中に「ちょっと待って!ここでどうなってるか見せて!」と言えるのがブレークポイントなんだね!

ブレークポイントの設置と削除

ブレークポイントを設置するには、コードエディタで停止させたい行の左側の余白(行番号の左側)をクリックします。

設置すると赤い丸(●)が表示され、その行に到達するとプログラムが停止します。再度クリックすることでブレークポイントを削除できます。

ブレークポイントの有効/無効

ブレークポイントを完全に削除せずに一時的に無効化することもできます。ブレークポイント上で右クリックし、「ブレークポイントの無効化」を選択します。

無効化されたブレークポイントは中抜きの丸(○)で表示され、プログラム実行時に停止しなくなります。

再度有効化するには、無効化されたブレークポイント上で右クリックし、「ブレークポイントの有効化」を選択します。

ブレークポイントの一覧

メニューバーで「デバッグ>ウィンドウ>ブレークポイント」を選ぶと、ブレークポイントの一覧を表示でき、各ブレークポイントの位置へジャンプ可能です。

プロ太

プロジェクト内のあちこちにブレークポイントを設置し、どこへ設置したかがわからなくなった場合は、これで確認するとよいですね。

ブレークポイント活用のコツ

ブレークポイントを多く設置しすぎてしまうと頻繁にプログラムが停止し、デバッグ効率が悪くなってしまいます。

なのであてずっぽうではなく、ある程度バグの原因になっていそうな箇所を推測し、怪しそうな箇所に配置するとよいでしょう。

デバッグにおいては、「仮説検証」の考え方が重要になります。以下でその考え方について簡単に触れているので、よければ参考にしてください。

C#入門編(6)エラーの種類とデバッグ方法 ~初心者が最低限覚えておきたいポイント~ 今回は、初心者がプログラミングをするときに、つまづきやすいエラーについての話をします。 プログラミングをしていると、確実にエラー...
プロ太

デバッグ実行をすると設置したブレークポイントでプログラムが停止し、プログラム内を確認できるようになります。

次に、デバッグ実行とその実行中の制御について説明をします。

デバッグ実行と制御

デバッグ実行の開始

デバッグモードでプログラムを実行するには、以下のいずれかの方法を使います。

  • F5キーを押す
  • メニューから「デバッグ」→「デバッグの開始」を選択
  • ツールバーの「開始」ボタン(緑色の三角形)をクリック
プロ太

簡単な「F5」を使うことが圧倒的に多いですね。Visual Studioユーザが頻繁に使うショートカットキーでしょう。

基本的なデバッグ実行の制御

デバッグ実行中、メニューの「デバッグ」から以下の操作が可能です。(カッコ内はショートカットキーです)

  • 一時中断:実行中のプログラムを一時的に中断(Ctrl+Alt+Break)
  • 続行:一時中断やブレークポイントで中断したプログラムの実行を再開(F5)
  • デバッグの停止:デバッグセッションを終了(Shift+F5)

プログラムがブレークポイント(もしくは一時中断)で停止すると、現在実行中の行の左側に黄色の矢印が表示されます。

これで、「プログラムの特定の行が実行されたかどうか?」というデバッグにおいて重要な情報を得ることが可能になるわけですね。

プロ太

デバッグにおいて特定行が実行されたかを確認するのは基本であり、バグ原因特定の第一歩です。

色々悩んだあげく、「実は、XXが実行されていた(or 実行されていなかった)ことが原因だった!」といったことはよくあることです。

ステップ実行

デバッグ実行中の便利な機能として「ステップ実行」があります。

ステップ実行とは、プログラムを1行ずつ順番に実行していく機能です。ブレークポイントなどで停止した後、プログラムの実行の流れを一歩ずつ追いかけることができます。

ステップ実行には主に3種類あります。デバッグ実行中にメニューの「デバッグ」から選択できます。また、ショートカットキーもそれぞれあります。

  • ステップイン(F11):現在の行を実行した後、メソッド呼び出しがある場合はそのメソッドの中に入っていく動作。
  • ステップオーバー(F10):現在の行を実行しますが、メソッド呼び出しがあってもその中には入らず、1行として実行して次の行に進む動作
  • ステップアウト(Shift+F11):現在実行中のメソッドの残りの部分をすべて実行し、呼び出し元のメソッドに戻る動作

以下の例で実際に使ってみましょう。

namespace ConsoleApp1
{
    internal class Program
    {
        public static void Main()
        {
            Console.WriteLine("メイン処理開始");
            int result = Calculate(5, 3);
            Console.WriteLine($"計算結果: {result}");
            Console.WriteLine("メイン処理終了");
        }

        private static int Calculate(int a, int b)
        {
            Console.WriteLine($"計算処理: {a} + {b}");
            return a + b;
        }
    }
}

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

例えば、Calculate(5, 3)という行で停止している状態で、ステップインを実行すると、Calculateメソッドの中に入ります。

一方、ステップオーバー実行をした場合にはCalculateメソッドの中には入りません。

ステップオーバー実行では、メソッドの実行が完了した後、次の行であるConsole.WriteLine($"計算結果: {result}");に移動します。

ステップアウト

例えばCalculateメソッド内のConsole.WriteLine($"計算処理: {a} + {b}");の行で停止している状態でステップアウトを実行をしてみましょう。

すると、Calculateメソッドの残りを実行し、MainメソッドのConsole.WriteLine($"計算結果: {result}");という行に戻ります。

ステップ実行の使い方のコツ

処理の流れを詳細に理解したい場合は、ステップインを使ってプログラムの詳細な動きを追跡します。

処理の詳細に興味がない場合は、ステップオーバーを使って詳細をスキップしながら効率よくデバッグを進められます。

ブレークポイントを使って関心のある箇所で停止させて、ステップ実行で詳細に調査するという流れが多いかと思います。

プロ太

特にF10(ステップオーバー)とF11(ステップイン)は頻繁に使うので、ショートカットキーを覚えておくと効率的にデバッグできますよ!

複雑なプログラムの動きを理解するのにとても役立ちます。

変数値の確認

プログラムのどこが実行されているかの情報とあわせて知りたいのが、プログラム停止位置における変数の値ですね。

メニューの「デバッグ>ウィンドウ>ローカル」で、変数値を確認することができます。

ステップ実行をしながら、変数値がどのように変わっていくかを確認するといったことも可能です。

プロ太

Visual Studioデバッガは、変数値を確認するための様々な方法を用意しています。

変数値確認については、次回の記事で詳しく解説します!

メソッド呼び出し履歴

プログラムではメソッドが別のメソッドを呼び出し、その連鎖で処理が進んでいきます。

さきほどの例では、MainメソッドがCalculateメソッドを呼び出していましたね。

メソッド呼び出しの履歴は「呼び出し履歴」ウィンドウ(コールスタック)で確認できます。

「return a + b;」の位置にブレークポイントを設置し、デバッグ実行して停止させて、メニューの「デバッグ>ウィンドウ>呼び出し履歴」を選択してみましょう。

呼び出し履歴は、現在実行中のメソッドから呼び出し元をさかのぼって表示します。最上部が現在実行中のメソッド、下に行くほど以前の呼び出し元になります。

プロ太

呼び出し履歴は「各メソッドがどのメソッドを呼び出したか」の履歴です。プログラムの実行経路を理解するのに役立ちます。

大きなプログラムでは、呼び出し履歴に数十個のメソッドが並ぶということもあります。

簡単なデバッグ実例

Visual Studioデバッガの基本機能を使った最小限の実例を紹介します。この例では、配列の要素を合計する単純なプログラムにバグがあり、それをデバッグで特定します。

以下は、配列要素を合計する簡単なプログラムですが、バグがあります。

namespace ConsoleApp1
{
    internal class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("配列の合計値を計算します");

            int[] numbers = { 10, 20, 30, 40, 50 };
            int sum = CalculateSum(numbers);

            Console.WriteLine($"合計値: {sum}");
            Console.ReadLine();
        }

        private static int CalculateSum(int[] values)
        {
            int total = 0;

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

            return total;
        }
    }
}

デバッグ手順を以下のように進めます。

1.問題の確認

プログラムを実行すると、配列の合計が150になるはずが、100と表示されます。

2.ブレークポイントの設定

プロ美

配列の初期化は間違ってなさそうだし、for文のあたりが怪しそう。

プロ太

for文にバグ原因がありそうという仮説ですね。ブレークポイントで停止させてその部分を確認してみましょう!

CalculateSum メソッド内のループの内側「total += values[i];」に赤い丸(●)が表示されるようにクリックしてブレークポイントを設置します。

3.デバッグ実行

F5キーを押してデバッグ実行を開始します。

4. ループの動作を確認

ブレークポイントで停止したら、F10キー(ステップオーバー)を数回押して、ループの動きを確認します。

プロ太

「続行(F5)」で、次にブレークポイントで停止するまで実行するという方法もありますね。

5. 変数値を確認

ローカル変数(ループカウンタi、合計値total)が次々に更新されていきます。ループ処理対象となっている配列要素の中身も正しいことがわかりますね。

ステップ実行を進めると、totalが100になった後にループが終了していることがわかります。最後の配列要素valuesの50が未処理になっています。

6.バグ原因の特定

ループ条件 「i < values.Length - 1」により、最後の要素(index=4)が処理されていないことが分かります。

プロ美

Visual Studioのデバッガを使ってバグ原因が特定できたよ!

7. 修正

ループ条件を「i < values.Length」へ変更すると、すべての要素が処理されるようにします。

プロ太

このようにデバッガを使うと、プログラムの中身を覗くことで、バグ原因の仮説検証のサイクルを素早く回すことができるのです。

まとめ

本記事では、プログラミングの効率を大きく高める「デバッガ」の基本と使い方について解説しました。

Visual Studioのデバッガ機能を使うことで得られる主な利点は以下の通りです。

  • プログラムの実行を特定の行で一時停止できる「ブレークポイント」機能
  • 1行ずつ処理を確認できる「ステップ実行」機能
  • プログラム実行中の変数値を確認できる機能
  • メソッドの呼び出し履歴(コールスタック)を確認できる機能

デバッグモードとリリースモードの違いや、ステップイン・ステップオーバー・ステップアウトといった基本的なデバッグ制御方法についても学びました。

デバッグは「仮説検証」の考え方が重要であり、エラーの原因を推測し、デバッガを使って検証していくプロセスが効率的なバグ解決につながります。

次回は、デバッガを使った「変数値の確認方法」について、より詳しく解説する予定です。

プロ太

引き続き、一緒にデバッガの使い方を学んでいきましょう!

ABOUT ME
プロ太
●仕事:現在は個人事業主(メンター・情報発信等)、大手IT企業で技術者・マネージャ(15年以上)、大学の外部講師、学生時代は学習塾で非常勤講師(約4年間) ●博士(工学)の学位取得 ●高校生の頃に独学で始め、プログラミング歴20年以上 ●言語:C# 、Java、C/C++、Python、JavaScript/TypeScript等 ●分野:Webアプリ、テスト自動化、生成AI、デバッガ、コード解析、ドメイン特化言語

ご依頼・ご相談について

プログラミング学習のご相談、お仕事のご依頼については、
こちらのお問い合わせページをご確認ください。