第6回 Windowsアプリのデバッグ&リリース連載:簡単! Visual Studio 2013入門(4/5 ページ)

» 2014年09月29日 18時40分 公開
[かわさきしんじ, Insider.NET編集部,共著]

VS 2013によるアプリのデバッグ方法

 デバッグの基本は、問題となっている可能性の高い箇所のコードを1ステップ(=1文)ずつ追跡して調べていくことである。それを行うには、怪しいと思われる箇所の一歩手前でプログラムの実行を一時的に停止させる必要がある。このプログラムの実行を一時停止する機能を「ブレークポイント」と呼ぶ。このデバッグ方法は、例えていうならば、DVDビデオを一時停止して(=ブレークポイント)、そこからコマ送りで再生する(=1ステップずつ追って調べる)という操作に似ている。

 今回のプログラムで問題となっている可能性の高いコードは、先ほど追加したフェードアウトのコードだ(なぜなら、フェードアウトを行う前は問題なく動作していたからだ)。そこで、menuItemClose_Clickメソッドの中にあるFormFadeOutメソッドにブレークポイントを仕掛けてみることにしよう。次の画面は、実際にブレークポイントを設定しているところだ。

ブレークポイントの設定 ブレークポイントの設定
menuItemClose_Clickメソッドの中にあるFormFadeOutメソッドにブレークポイントを設定したところ。ブレークポイントを設定するには、該当行にカーソルを移動し、[F9]キーを押すだけである(もしくは左端の赤いの部分をクリックしてもよい)。逆に、ブレークポイントを解除する場合も[F9]キーを押せばよい。もし複数個所に設定したブレークポイントを一括解除したい場合には、[Ctrl]+[Shift]+[F9]キーを押せばよい。

 ブレークポイントを設定したら、[F5]キーを押すか、メニューバーから[デバッグ]−[デバッグ開始]をクリックして、デバッグ実行を開始する。

 デバッグが開始されると「時計」アプリが起動するので、右クリックでコンテキストメニューを表示して[終了]を実行してみよう。すると、次の画面のようにブレークポイントを設定した位置で処理が停止するはずだ。

ブレークポイントの位置で処理が停止した画面 ブレークポイントの位置で処理が停止した画面
ブレークポイントを設定したFormFadeOutメソッドの呼び出し位置で処理が停止したところ。停止している箇所は黄色の矢印で示されている。

 処理を1ステップ(=1文)進めるには、[F10]キーを押す(「ステップオーバー」と呼ばれる)。また、メソッド内の処理に入るには、[F11]キーを押す(「ステップイン」と呼ばれる)。ここでは、FormFadeOutメソッド内部の処理を調べたいので、ステップインの[F11]キーを押す。すると、次の画面のように、FormFadeOutメソッドの内部に移って処理が停止する。

ステップインしたメソッド内で処理が停止した画面 ステップインしたメソッド内で処理が停止した画面
[F11]キーを押して、FormFadeOutメソッド内部に入って処理が停止したところ。
  (1) FormFadeOutメソッドの実装開始部分(「{」の場所)で処理が停止している。停止している箇所は黄色の矢印で示されている。
  (2) [呼び出し履歴]ウィンドウ(「コールスタック」とも呼ばれる)。[呼び出し履歴]ウィンドウを表示するには、メニューバーから[デバッグ]−[ウィンドウ]−[呼び出し履歴]を選択すればよい。このウィンドウでは、現在の処理がどういう順番で呼び出されたのかが分かる。直近に呼び出されたメソッドが最上位に、そのメソッドを呼び出したメソッドがその下に……という順序で、呼び出しのスタート地点が一番下に表示される。例えばこの画面では、最初に「MyClock.exeのMyClock名前空間のDisplayクラスのMainメソッド」が呼ばれ(一番下)、その次に「DisplayクラスのmenuItemClose_Clickメソッド」が呼ばれ(上から2つ目)、最後に「FormFadeOutメソッド」が呼ばれている(一番上)ことが分かる。この画面の例は単純だが、メソッドの呼び出しが複雑な場合、この[呼び出し履歴]ウィンドウが役立つことがある。[呼び出し履歴]ウィンドウ内のメソッドをダブルクリックすれば、そのメソッド呼び出しの該当行にジャンプできる。[外部コード]というのは、大ざっぱには.NET Frameworkが提供するコードのことだ。どんなメソッドが実際に呼び出されているかは[呼び出し履歴]ウィンドウを右クリックしてコンテキストメニューから[外部コードの表示]を選択すればよい。あまりに多くのメソッドが表示されるのでビックリするかもしれないが、Windowsアプリはこのように自分が書いたコードと.NET Frameworkが提供するコードが深く絡み合って実行されていることがよく分かるだろう。

 次に[F10]キーでステップオーバーして、FormFadeOutメソッドの処理を1ステップずつ進めていってみよう。すると、forループの間をぐるぐると繰り返し実行しているのが分かるだろう。ここで、forループ内にある、変数「n」の値やOpacityプロパティの値がバグの原因として疑わしいので、どうなっているか調べてみよう。これを調べるには、次の画面のように[ウォッチ]ウィンドウを使う。

[ウォッチ]ウィンドウによる変数状態の確認 [ウォッチ]ウィンドウによる変数状態の確認
[ウォッチ]ウィンドウで変数の状態を確認しているところ。[ウォッチ]ウィンドウを表示するには、メニューバーから[デバッグ]−[ウィンドウ]−[ウォッチ]−[ウォッチ 1]を選択すればよい。
  (1) [ウォッチ]ウィンドウで調べたい変数やプロパティ、メソッドなどを選択して(ダブルクリックで単語を選択できる)、[ウォッチ]ウィンドウ内にドラッグ&ドロップする。
  (2) [ウォッチ]ウィンドウに追加された変数やプロパティの値は、処理を1ステップ進めるごとにリアルタイムに更新される。
  (3) 変数やプロパティの上にマウスカーソルを乗せることで、その変数やプロパティの状態をツールチップで表示できる。

 [ウォッチ]ウィンドウで変数「n」の値を参照すると、「49」から減るはずの値が「51」と逆に増えている。つまりforループのコードで、カウントアップ(=インクリメント)するのは間違いなのだ(「n++」は1つずつカウントアップするという意味)。

for (int n = 49; n >= 0; n++)

forループでカウントアップする間違ったコード

 正しくは、次のようにカウントダウン(=デクリメント)しなければならなかったわけだ(「n--」は1つずつカウントダウンするという意味)。

for (int n = 49; n >= 0; n--)

forループでカウントダウンする正しいコード

 このコーディングミスにより、プログラムは無限に(厳密には数値の範囲があるので有限だが……)カウントアップし続け、アプリがフリーズした(「応答なし」の)状態になっていたわけだ。

 バグの箇所が判明したので、[Shift]+[F5]キーを押すか、メニューバーから[デバッグ]−[デバッグの停止]を選択するかして、デバッグ実行を終了する。そして、先ほどのforループのコードの誤りを修正して、再ビルドを行いもう一度デバッグ実行をしてみよう。

 フォームを右クリックしてコンテキストメニューから[終了]を選択し、FormFadeOutメソッドで実行が止まったら、先ほどと同様な手順でステップ実行を行い、フォームのOpacityプロパティ(this.Opacity)の値が減っていることを[ウォッチ]ウィンドウで確認する。確認ができたら、全体の動作についても確認しておこう。これには[F5]キーを押すかメニューバーから[デバッグ]−[続行]を選択すればよい。すると、次は正常にフェードアウトしながら、アプリが終了するはずだ。

 以上でプログラムは完成した。せっかく作ったので、このプログラムを実際にユーザーに使ってもらえるようにしてみよう。次に、プログラムのリリースと配布について簡単に解説しておく。

Copyright© Digital Advantage Corp. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。