連載:Visual Studioデバッグ手法

第1回 Visual Studio 2010のデバッグ機能をまとめる

亀川 和史
2010/06/09
Page1 Page2 Page3

 「デバッグ」というと、どのような作業を思い浮かべるだろうか? 地道な作業? それとも、達人が「ここだ!」と一瞬にして修正するが、一般の開発者には難しい作業? 普通の開発者が、デバッグ作業をもっと効率よく行う方法はないのだろうか?

 IDEについて、ちょっとしたことを知っていると、プログラミングの効率が上がる。デバッグも同様で、デバッガをうまく使いこなすことで、格段に効率よく行えるようになる。Visual Studioには、デバッグを支援するための便利なデバッガ機能が多く搭載されているためだ。

 本連載ではまず、Visual Studioのデバッガの基本的な使い方を紹介する。デバッガ機能およびデバッグ手法について、マネージ・コード中心で紹介するが、必要に応じてアンマネージ・コードについても紹介する。具体的には、以下の話題について取り上げる。

  • 第1回:Visual Studioのデバッガ機能紹介、および、Windowsのエラー・コード基礎知識
  • 第2回:IntelliTraceの活用方法
  • 第3回:さまざまな状況のデバッグ方法

デバッグの事前準備:バグ情報の収集方法

 Visual Studio 2010を用いたデバッグ手法の基本を説明する前に、バグに関する情報を収集する方法について説明する。

事前の情報収集

 アプリケーションのデバッグ作業を始める前に、バグが発生した状況を確認しよう。開発中のプログラムでバグが発生したのであればすぐに情報を収集できるが、エンド・ユーザー環境でバグが発生した場合には、そのユーザーから情報を収集する必要がある。

 具体的には以下のような情報を収集すると、その後のデバッグ作業がスムーズにいく。

(1)使用しているWindows OSのバージョン、サービスパックのバージョン、およびインストール済みアプリケーションやパッチなど(これらの情報はすべてMicrosoft Configuration Captureユーティリティ(=Microsoft Product Support Reports)で取得できる。マシンの多様な情報を採取するため、マシン・スペックにもよるが、実行完了まで数分程度必要になる)。

(2)「どのように操作したら発生したか?」の具体的な手順。Windows 7などでは、問題ステップ記録ツール*1を使って手順を記録してもらい、そのデータ(=ZIP形式で圧縮されたMHTML形式のWebページ)を送付してもらえば、より早く解決できる可能性がある

(3)発生したエラーの内容。Windows 7/Windows Vistaなどでは、アプリケーションの信頼性モニタ(後述)で過去にさかのぼって、いつどんなアプリケーション・エラーが発生したのか記録されているため、後から参照する場合でも見やすく表示される

*1 問題ステップ記録ツールに関する詳細は、以下の記事を参考にしてほしい。

 (3)の情報収集の手順については、もう少し掘り下げて説明しよう。

信頼性モニタによるエラー情報の収集

 エラーが発生した場合、まずはアプリケーションの利用者に信頼性モニタを起動して、そこで得られるメッセージ(=後述の[問題の詳細]の情報)をそのまま開発者に送ってもらう。次の画面は、Windows 7の信頼性モニタを起動したところだ。

Windows 7の信頼性モニタ
起動するには、[スタート]メニューの[プログラムとファイルの検索]テキストボックスに「信頼性」と入力し、表示される検索結果から[信頼性の履歴の表示]をクリックすればよい。
  [解決策の確認]というリンクをクリックすると、マイクロソフトに情報が送信され、解決策が提示される場合がある。今回は使用しない。

 該当する日付の[アプリケーション エラー]の行にある[×]をクリックすると、[信頼性の詳細を表示]のリストに、その日に発生したアプリケーション・エラーの一覧が表示される。

 次に、以下の画面の例のように、該当するアプリケーション・エラー項目を右クリックして、そこで表示されるコンテキスト・メニューから[技術的な詳細の表示]をクリックする。

アプリケーション・エラーの技術的な詳細の表示

 これにより、次の画面のような[問題の詳細]が表示される。

.NETアプリケーション・エラー個別の[問題の詳細]
エンド・ユーザーに、この詳細情報を開発者/サポートに送ってもらう。
  .NET Frameworkの場合、ランタイムの例外情報が得られる。

 [クリップボードにコピー]リンクをクリックすれば、[問題の詳細]の情報がそのままクリップボードにテキストとしてコピーされる。エンド・ユーザーは、メールなどの指定された方法で、そのテキストを開発者やサポートに送ればよい。

 ここで、「例外コードの情報を受け取っても、どうしてよいか分からない」という意見もあるかもしれない。次に例外情報の活用方法を説明しよう。

.NET Frameworkの場合の例外情報の活用方法

 .NET Frameworkの場合、ランタイム(=CLR)の例外が上の画面の?のように記録されているので、それをデバッグの手掛かりにできる。上の画面の例では、「System.IO.DirectoryNotFound」という例外が出ているため、ディレクトリ関係の処理で例外が発生したと考えられる。

アンマネージ・コードの場合の例外情報の活用方法

 アンマネージ・コードの場合、.NET Frameworkの場合のような分かりやすい形でのエラー情報は得られず、例外コードとして取得することになる。

Win32アプリケーション・エラー個別の[問題の詳細]
エンド・ユーザーに、この詳細情報を開発者/サポートに送ってもらう。
  アンマネージ・コード(=Wi32などのネイティブ・アプリケーション)の場合、ランタイムの例外情報はコードとして表示される。

 上の画面の例は、同じようにわざとアプリケーション例外を起こさせたプログラムでの信頼性レポートである。アンマネージ・コードの場合、上の画面のの例外コードはどんな原因でエラーが発生したかという重要な情報源になる。

 イベント・ビューア内で「アプリケーション・エラーです。エラー・コードは0xC0000005です」のように表示されるエラーをログなどで見たことがないだろうか? 上の画面のの例外コードはこれと同じものである。

 Windowsにおいて、アプリケーションの問題や設定ミスなどでプログラムに異常が発生した場合、発生原因によって例外コード(=Win32エラー・コード)が決められている。Win32エラー・コードの仕様(=32bit値のビット・レイアウト)は、下記の表のように定義されている。

 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+---+-+-+-----------------------+-------------------------------+
| S |C|R|     Facility          |               Code            |
+---+-+-+-----------------------+-------------------------------+
Bit 説明
31〜30 (S)セキュリティ・コード。重要度を表す。組み合わせは以下のとおり。
00:成功
01:情報
10:警告
11:エラー
29 (C)カスタマー・コード・フラグ(=マイクロソフト以外のベンダが独自に定義した例外コードかどうか)
28 (R)予約済み
27〜16 (Facility)ファシリティ・コード(=エラーの発生源となっている機能や技術を分類する。例えばWindows標準やRPCなど)
15〜0 (Code)ファシリティの状態コード
Win32エラー・コードの仕様(=32bit値のビット・レイアウト)
Visual StudioでVisual C++とともにインストールされるWindows SDKのヘッダ・ファイル「winerror.h」を見てみよう(既定で「C:\Program Files\Microsoft SDKs\Windows\SDKバージョン番号\Include」にインストールされている)。このファイル内に、Win32エラー・コードが定義されている。
「エラー」を意味するコードは「0xC」で始まることになる。

 例えば、先ほどの「Win32アプリケーション・エラー個別の[問題の詳細]」のの「0xC0000409」(16進数表記)は、ビットに変換すると、先頭2bitの31〜30bit目が「11」なので、「エラー」を表すことになる。

 また、COM(Component Object Model)場合は、これを少し変更した仕様(=32bit値のビット・レイアウト)が、下記の表のように定義されている。

 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1
 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+-+-+-+-+-+---------------------+-------------------------------+
|S|r|C|R|r|     Facility        |               Code            |
+-+-+-+-+-+---------------------+-------------------------------+
Bit 説明
31 (S)セキュリティ・コード。組み合わせは以下のとおり。
0:成功
1:エラー
30 (r)予約済み
29 (C)カスタマー・コード・フラグ
28 (R)予約済み
27 (r)予約済み
26〜16 (Facility)ファシリティ・コード
15〜0 (Code)ファシリティの状態コード
COMエラー・コードの仕様(=32bit値のビット・レイアウト)
Visual StudioでVisual C++とともにインストールされるWindows SDKのヘッダ・ファイル「winerror.h」を見てみよう(既定で「C:\Program Files\Microsoft SDKs\Windows\SDKバージョン番号\Include」にインストールされている)。このファイル内に、Comエラー・コード(COM Error Codes)が定義されている。
「エラー」を意味するコードは「0x8」で始まることになる。

 Windowsのエラーで「0x80004001」という形式のエラーを見ることがあるだろう。0x80000000番台の「エラー」は、(基本的に)COMのエラーになっている(Win32エラー・コードで0x80000000番台は、セキュリティ・コードが「10:警告」となる)。これを知っているだけでも調査の初段階で助かることになるだろう。

 これらのエラー・コードはVisual Studioに付属している(Visual C++のみExpress Editionにも付属している)エラー・ルックアップというツールを使用すれば、エラー・コードの意味を調べることができる。エラー・ルックアップを使うには、Visual StudioのIDEのメニューバーから[ツール]−[エラー ルックアップ]を選択すればよい。次の画面はその例。

エラー・ルックアップへのショートカットが登録されているメニューバー
メニューバーにない場合、Visual Studio 2008なら「C:\Program Files\Microsoft Visual Studio 9.0\Common7\Tools\errlook.exe」、Visual Studio 2010なら「C:\Program Files\Microsoft Visual Studio 10.0\Common7\Tools\errlook.exe」に配置されているものを直接起動するとよい。

 エラー・ルックアップを使うとき、ちょっとした注意点がある。「0xC」で始まるWin32エラー・コードは15bit目以下の値だけを入れ、「0x8」で始まるCOMのエラーをそのまま入力する必要がある。以下に「0xC」で始まるWin32エラー・コードの例を示す。

エラー・ルックでのWin32エラー・コードの検索例

 次にCOMエラー・コードの場合、例外コードをそのまま指定する。

エラー・ルックでのCOMエラー・コードの検索例

 プログラムが何らかのエラーを起こした場合、このようなエラー・コードをログ(イベント・ビューアのアプリケーション・ログが代表的な格納場所)やメッセージとして記録している場合が多い。このエラー・コードとエラーの再現手順の連絡を(エンド・ユーザーから)受けて、プログラマーはデバッグを行うことになる。

 次のページからはVisual Studio 2010が持つデバッグ機能を紹介する。


 INDEX
  [連載]Visual Studioデバッグ手法
  第1回 Visual Studio 2010のデバッグ機能をまとめる
  1.デバッグの事前準備:バグ情報の収集方法
    2.Visual Studio 2010を使用したデバッグ作業の基本(1)
    3.Visual Studio 2010を使用したデバッグ作業の基本(2)

インデックス・ページヘ 「連載:Visual Studioデバッグ手法」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH