デバッグって何? どうやってやるの?
debugクラスを使ってログを出してみたい
こんにちは。文系出身で今年現役8年目エンジニアになる佐藤です。
皆さんはC#でプログラミングしたあと、デバッガを使いデバッグをしていますか? また、ログなどで自分の作ったプログラムが正常に動いているか確認したことはあるでしょうか?
この記事では、visual studioのデバッガを使用してデバッグをするポイントや手順を解説していきます。また、debugクラスを使って、自分で設定した内容を出力する方法も合わせて解説していきます。
プログラミングスキルと同じくらいデバッグのスキルも重要な要素なので、この記事で基礎から学習していきましょう。
それでは、さっそくC#のプログラムをデバッグする方法を見ていきましょう。
C#のプログラムをデバッグする方法
この章では、C#のプログラムをデバッグする2つの方法について紹介していきます。また、どうやって使い分けたら良いのかという点も説明していきます。
visual studioのデバッガを使う
まず初めに紹介するのはデバッガを使う方法です。デバッガにはいろいろな機能があり、統合開発環境のvisual studioにも搭載されています。
できることを大まかに紹介すると
- プログラムを設定したタイミングで一時停止することができる
- 一時停止したところから一行ずつ動きを確認することができる
- 一時停止した時に変数に格納されている値などを確認することができる
- メソッドや関数が呼び出されている順番を表示できる
visual studioのデバッガでは、作成したプログラムがどのように動いているのかチェックすることができるんです。
短いコードならデバッガを使わなくても動きが分かるかもしれませんが、大きいシステムになればデバッガを使って不具合などを探すことが多くなります。後ほど、詳しい使用方法については説明します。
debugクラスを使って出力する
次に、debugクラスを使うことで自分が設定した言葉を出力してデバッグする方法もあります。これを使えば、デバッガが無くても正しく動いているのか判断することができます。
どんなものなのかは、実際に使っているサンプルコードをみて確認していきましょう。実行すると、変換された日付がコンソール画面に出力されます。
開発者の意図はこのような状況です。
- 変換後の日付は変換前と違わないか確認したい。
- 変換前の日付をコンソールに表示したくない。
using System; using System.Diagnostics; namespace test { class Program { static void Main(string[] args) { DateTime nowTime = DateTime.Now; Debug.WriteLine("変換前の時刻は:" + nowTime); Console.WriteLine("今は" + nowTime.ToString("yyyy/MM/dd HH:mm") + "です!"); Console.ReadKey(); } } }
実行が完了したあと、下のほうにある「出力」欄をみてください。
12行目で指定した言葉と、変換前の日付が表示されていますよね。これを見れば、コンソール画面出力された日付や日時が変換前と同じだということが分かります。
debugクラスはこんなふうに使うことができるんです。
どうやって使い分けるのか
2つの方法があると、どっちを使えばいいのか迷ってしまいますよね。
どちらも一緒に使ってしまっても構わないのですが、初心者の方はまずデバッガを使って自分のプログラムが正しく動いているのかチェックすることから始めてみましょう。
一時停止して一行ずつ確認することで、上手くいかない原因や勘違いを見つけることができます。プログラミングをしていくならデバッガを使ってのチェックは避けて通れないものなので始めのうちから練習しておくことをお勧めします。
デバッグのコツはこの後紹介していきますので、一緒にやり方を覚えていきましょう!
逆に、起動から終了までの一貫した動きの記録を取りたいという状況ならdebugクラスの仕様をお勧めします。
デバッガとは違い、debugクラスを使えば終了した後に出力された内容を確認することができます。起動から終了まで、処理にどれくらいの時間がかかったなど、一時停止したらチェックできないような内容を確認することができるんです。
状況に応じて使い分けていけるように、デバッグにも慣れていきましょう。それでは次はデバッガの使い方とデバッグのポイントを解説していきます。
デバッガの使い方
この章ではvisual studioのデバッガの使い方と、デバッグの手順を解説していきます。
初心者の方にとっては「上手く動かないなら、デバッグしてみて」といきなり言われても手順や見るポイントがわかりませんよね。手順とその時見るべきポイントをまとめて紹介していきますので、一緒に手を動かして学習していきましょう。
まずはブレークポイントを設定してみよう
デバッグの最初は、自分の書いたコードのどこで一時停止させるかを決定することから始めましょう。一時停止する場所のことを「ブレークポイント」と呼びます。
今回デバッグしてみるサンプルコードはこちらです。
namespace test { class Program { static void Main(string[] args) { int i = 0; for (int r = 1; r <= 10; r++) { i = i + r; } System.Console.WriteLine(i); System.Console.ReadKey(); } } }
ブレークポイントを設定する方法はとっても簡単、画像のオレンジで囲った灰色の部分をクリックするだけです。
今回は9行目に設定します。クリックして赤い丸が表示されれば設定はOKです。
今回は9行目に設定しましたが、慣れるまでどこに設定したらいいのか迷いますよね。そういう時には次のポイントで設定してみましょう。
ブレークポイントが設定できる一番上の行に設定してみる
まずは一時停止させることが大切なので、迷ったら一番最初に設定してみましょう。クラス宣言の部分などは設定できませんので、このサンプルコードだと一番最初は6行目に設定することができます。
ループに入る前、ループ中の処理に設定してみる
ループは予期しない不具合が起こり、無限ループに陥ってしまう可能性もあります。そうならないためにもループに入る前や、中の処理にブレークポイントを設定するのも非常に大切です。このサンプルコードなら9行目や11行目になります。
不具合の原因かもと予想している場所に設定してみる
自分で「ここが怪しいのでは?」と予想ができているなら、その前にブレークポイントを設定してみるのもよいでしょう。ただ、予想が外れるなどして不具合の原因を見つけるまでに時間がかかってしまうこともあるので、あまり過信しすぎないようにしましょう。
ブレークポイントを設定できたら、このボタンを押してデバッガを起動します。
設定したポイントで一時停止しましたか? きちんと一時停止したら、次のステップに移りましょう。
コードを一行ずつ実行してみる
設定したポイントで一時停止できたら、ここから一行ずつ確認することができます。いま止まっている行は黄色でハイライトされているので確認しましょう。
コードを一行ずつ進めることを「ステップイン」と呼びます。F11を押せばステップインすることができるので、やってみましょう。
評価の式ごとに黄色のハイライトが動いたのが確認できたでしょうか? これを繰り返すことで、予想していた通り動いているかを確認することができます。次に解説する値の確認方法を合わせてデバッグをしてみましょう。
変数にはどんな値が入っているのか確認しよう
一時停止した時、変数にはどんな値が入っているのか確認することがデバッガでは可能です。確認する方法は2つあり、手軽に確認したいなら変数自体にマウスオーバーします。
変数rにカーソルを当て続けると、にょきっと下に変数の値情報が出てきます。何回かF11で動かしたので、rには今3が格納されているようです。
もう一つの方法は、ウォッチウィンドウに登録する方法です。この方法なら、変数が変わっていく様子も確認することができますし、複数の変数を確認し続けることができます。
登録の仕方は、ウォッチウィンドウの名前欄に直接変数名を入力する、もしくは変数を選択状態にしてドラッグアンドドロップします。
ウォッチがない、という方は デバッグ⇒ウィンドウ⇒ウォッチ⇒ウォッチ1 を選んで表示させましょう。
これでデバッグひとまずデバッグすることができます。F11でコードを進めながら「変数に入っている値は合っているのか?」「考えていた回数ループしてくれているか?」などを確認していきましょう。
次に、ちょっと便利な小技の紹介をします。
デバッガを使う上での小技紹介
長いコードをデバッグしてるとき、別のメソッドに飛んでしまったりしてデバッグしにくいなという事もでてきます。そんな時はF10(ステップオーバー)を使ってみましょう。
一時停止のカーソルが別のメソッドに飛ぶことなく、次の行へ移ることができます。
また、指定の場所まで処理を進めてほしいときはこの▶を押してください。
これをクリックすると、そこまで処理を進めてくれます。長いコードで、飛ばしたい部分がある時には活用してみてください。
debugクラスの使い方
この章ではdebugクラスを使用して、設定した内容を主力する方法を解説します。テキストに保存する方法も紹介するので、ログを出してみたいと考えている方はぜひご覧ください。
よく一緒に解説されるtraceクラスとは?
debugクラスを使う前に、よく一緒に解説されるtraceクラスについても知っておきましょう。
traceクラスとdebugクラスの動きは全く変わりません、指定した言葉を出力してくれます。じゃあ何が違うのかというと、構成によって呼び出されるかどうかの違いがあるんです。
ビルドする時に、構成を「Debug」や「Release」に変更できるのですが、debugクラスは構成がDebugの時のみ動作します。そして、traceクラスはどちらの構成でも動作します。
もし、あなたが作成したプログラムをリリースする際にもログを出したいということなら「trace」クラスを使用して出力するようにプログラミングしましょう。
それでは、いよいよ基本の書き方等を解説していきます。
基本の書き方
debugクラスの使い方は簡単です。一番最初に見たサンプルコードから抜粋するので、書き方を見てみましょう。
Debug.WriteLine(nowTime);
「WriteLine」というメソッドは、()の中の文字列を出力した後改行する命令です。もし改行が要らないなら「Write」を使用します。
これで、出力タブに文字列が表示されるようになりました。
次に応用編として、条件に当てはまった時だけ文字列を出力する方法をご紹介します。
条件に当てはまった時だけ出力する方法
わざわざif文を使わなくても、debugクラスだけで条件に合ったときだけ出力することができるんです
「WriteLineIf」というメソッドを使って書くことで実装できます。
using System.Diagnostics; namespace test { class Program { static void Main(string[] args) { int age = 20; Debug.WriteLineIf(age >= 20,"変数ageの値は"+age); } } }
変数ageが20以上の時に、文字列が出力されるようなコードです。()の中には「条件式,文字列」を入力していきます。こちらも、改行が必要ないときは「WriteIf」を使用します。
最後に、出力した内容をテキストで保存する方法について解説していきます。
出力内容をテキストに保存する方法
debugもしくはtraceで実行ログを出力してみたいという時もありますよね。そんな時には、出力内容をテキストで保存する方法をお試しください。
using System; using System.Diagnostics; namespace test { class Program { static void Main(string[] args) { DefaultTraceListener dtl= (DefaultTraceListener)Debug.Listeners["Default"]; dtl.LogFileName = @"C:satodebug_test.txt"; Debug.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " ログ出力開始"); Debug.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " 処理中"); Debug.WriteLine(DateTime.Now.ToString("yyyy/MM/dd HH:mm:ss") + " ログ出力終了"); } } }
debug_log.txt
2019/06/17 15:33:47 ログ出力開始 2019/06/17 15:33:47 処理中 2019/06/17 15:33:47 ログ出力終了
DefaultTraceListenerオブジェクトを生成し、LogFileNameを設定することで指定した場所にファイルを出力することができます。このように時間と、処理内容を記載すると簡単な実行ログとして活躍できるかと思います。
もちろん、先程紹介したWriteLineIfを使用することもできますので状況に応じてデバッグメッセージを設定してみてくださいね。
まとめ
C#でデバッグする方法を2つを解説しました。
デバッグはプログラミングする上で必ず通る道ですので、練習のうちから慣れていきましょう。
それでは、次の解説で!