クラッシュ ダンプ分析
すべてのバグがリリース前に見つかるわけではないため、例外をスローするすべてのバグがリリース前に見つかるわけではないことを意味します。 幸いなことに、Microsoft は、ユーザーが発見した例外に関する情報を開発者が収集できるようにする機能を Platform SDK に組み込んでいます。 MiniDumpWriteDump 関数は、プロセス領域全体を保存せずに、必要なクラッシュ ダンプ情報をファイルに書き込みます。 このクラッシュ ダンプ情報ファイルはミニダンプと呼ばれます。 この技術記事では、ミニダンプの書き方と使用方法について説明します。
ミニダンプの作成
ミニダンプを書き込むための基本的なオプションは次のとおりです。
何もしない。 Windows は、プログラムが未処理の例外をスローするたびに、自動的にミニダンプを生成します。 ミニダンプの自動生成は Windows XP 以降で利用できます。 ユーザーが許可した場合、ミニダンプは Windows エラー報告 (WER) を通じて開発者ではなく Microsoft に送信されます。 開発者は、 Windows デスクトップ アプリケーション プログラムを通じてこれらのミニダンプにアクセスできます。
WER を使用するには以下が必要です。
- 開発者はAuthenticodeを使用してアプリケーションに署名する
- アプリケーションは、すべての実行ファイルとDLLに有効なVERSIONINFOリソースを持っています。
未処理の例外に対するカスタム ルーチンを実装する場合は、例外ハンドラーで ReportFault 関数を使用して、自動化されたミニダンプを WER に送信することを強くお勧めします。 ReportFault 関数は、WER への接続とミニダンプの送信に関するすべての問題を処理します。 ミニダンプを WER に送信しないと、Games for Windows の要件に違反します。
WER の詳細については、 Windows エラー報告を参照してください。
Microsoft Visual Studio Team System の製品を使用します。 デバッグ メニューで、 ダンプを名前を付けて保存 をクリックして、ダンプのコピーを保存します。 ローカルに保存されたダンプの使用は、社内テストおよびデバッグにのみ使用できます。
プロジェクトにコードを追加します。 MiniDumpWriteDump 関数と適切な例外処理コードを追加して、ミニダンプを保存し、開発者に直接送信します。 この記事では、このオプションを実装する方法を説明します。 ただし、 MiniDumpWriteDump は現在マネージ コードでは動作せず、Windows XP、Windows Vista、Windows 7 でのみ使用できることに注意してください。
スレッド セーフ
MiniDumpWriteDump は DBGHELP ライブラリの一部です。 このライブラリはスレッドセーフではないため、 MiniDumpWriteDump を使用するプログラムは、 MiniDumpWriteDumpを呼び出す前にすべてのスレッドを同期する必要があります。
コード付きミニダンプの作成
実際の実装は簡単です。 以下は、 MiniDumpWriteDumpの使用方法の簡単な例です。
#include <dbghelp.h>
#include <shellapi.h>
#include <shlobj.h>
int GenerateDump(EXCEPTION_POINTERS* pExceptionPointers)
{
BOOL bMiniDumpSuccessful;
WCHAR szPath[MAX_PATH];
WCHAR szFileName[MAX_PATH];
WCHAR* szAppName = L"AppName";
WCHAR* szVersion = L"v1.0";
DWORD dwBufferSize = MAX_PATH;
HANDLE hDumpFile;
SYSTEMTIME stLocalTime;
MINIDUMP_EXCEPTION_INFORMATION ExpParam;
GetLocalTime( &stLocalTime );
GetTempPath( dwBufferSize, szPath );
StringCchPrintf( szFileName, MAX_PATH, L"%s%s", szPath, szAppName );
CreateDirectory( szFileName, NULL );
StringCchPrintf( szFileName, MAX_PATH, L"%s%s\\%s-%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp",
szPath, szAppName, szVersion,
stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay,
stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond,
GetCurrentProcessId(), GetCurrentThreadId());
hDumpFile = CreateFile(szFileName, GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_WRITE|FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0);
ExpParam.ThreadId = GetCurrentThreadId();
ExpParam.ExceptionPointers = pExceptionPointers;
ExpParam.ClientPointers = TRUE;
bMiniDumpSuccessful = MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),
hDumpFile, MiniDumpWithDataSegs, &ExpParam, NULL, NULL);
return EXCEPTION_EXECUTE_HANDLER;
}
void SomeFunction()
{
__try
{
int *pBadPtr = NULL;
*pBadPtr = 0;
}
__except(GenerateDump(GetExceptionInformation()))
{
}
}
この例では、 MiniDumpWriteDump の基本的な使用方法と、それを呼び出すために必要な最小限の情報を示します。 ダンプ ファイルの名前は開発者次第ですが、ファイル名の競合を避けるために、アプリケーションの名前とバージョン番号、プロセス ID とスレッド ID、日付と時刻からファイル名を生成することをお勧めします。 これは、ミニダンプをアプリケーションとバージョン別にグループ化するのにも役立ちます。 ミニダンプ ファイル名を区別するためにどの程度の情報を使用するかは開発者が決定します。
上記の例のパス名は、 GetTempPath 関数を呼び出して一時ファイル用に指定されたディレクトリのパスを取得することによって生成されたことに注意してください。 このディレクトリの使用は、権限が最小限のユーザー アカウントでも機能し、ミニダンプが不要になった後にハード ドライブの領域を占有するのを防ぎます。
毎日のビルド プロセス中に製品をアーカイブする場合は、必要に応じて製品の古いバージョンをデバッグできるように、ビルドのシンボルも必ず含めてください。 また、シンボルを生成する際に完全なコンパイラ最適化を維持するための手順を実行する必要があります。 これを行うには、開発環境でプロジェクトのプロパティを開き、リリース構成の場合は次の操作を実行します。
- プロジェクトのプロパティ ページの左側で、C/C++ をクリックします。 デフォルトでは、 一般 設定が表示されます。 プロジェクトのプロパティ ページの右側で、 デバッグ情報の形式 を プログラム データベース (/Zi)に設定します。
- プロパティ ページの左側で、 リンカーを展開し、 デバッグをクリックします。 プロパティ ページの右側で、 デバッグ情報の生成 を はい (/DEBUG)に設定します。
- 最適化をクリックし、 参照 を参照されていないデータの削除(/OPT:REF)に設定します。
- COMDAT フォールディングを有効にする を 冗長 COMDAT を削除する (/OPT:ICF)に設定します。
詳細については、 MINIDUMP_EXCEPTION_INFORMATION 構造体と MiniDumpWriteDump 関数を参照してください。
Dumpchk.exe の使用
Dumpchk.exe は、ダンプ ファイルが正しく作成されたかどうかを確認するために使用できるコマンド ライン ユーティリティです。 Dumpchk.exe がエラーを生成する場合、ダンプ ファイルは破損しており、分析できません。 Dumpchk.exe の使用方法については、「Dumpchk.exe を使用してメモリ ダンプ ファイルをチェックする方法」を参照してください。
Dumpchk.exe は Windows XP 製品 CD に含まれており、Windows XP 製品 CD の Support\Tools\ フォルダーにある Setup.exe を実行することで、System Drive\Program Files\Support Tools\ にインストールできます。 また、Windows Hardware Developer Central の Windows デバッグ ツール から入手可能なデバッグ ツールをダウンロードしてインストールすることで、Dumpchk.exe の最新バージョンを入手することもできます。
ミニダンプの分析
ミニダンプを分析用に開くのは、作成するのと同じくらい簡単です。
ミニダンプを分析するには
- Visual Studio を開きます。
- ファイル メニューで、 プロジェクトを開くをクリックします。
- ファイルの種類 を ダンプ ファイルに設定し、ダンプ ファイルに移動して選択し、 開くをクリックします。
- デバッガーを実行します。
デバッガーはシミュレートされたプロセスを作成します。 シミュレートされたプロセスは、クラッシュの原因となった命令で停止されます。
Microsoft パブリック シンボル サーバーの使用
ドライバーレベルまたはシステムレベルのクラッシュのスタックを取得するには、Microsoft パブリック シンボル サーバーをポイントするように Visual Studio を構成する必要がある場合があります。
Microsoftシンボルサーバーへのパスを設定するには
- デバッグ メニューで、 オプションをクリックします。
- オプション ダイアログボックスで、 デバッグノードを開き、 シンボルをクリックします。
- デバッグ時にシンボルを手動でロードする場合を除き、 シンボルが手動でロードされた場合にのみ上記の場所を検索する が選択されていないことを確認してください。
- リモート シンボル サーバーでシンボルを使用している場合は、シンボルをコピーできるローカル ディレクトリを指定することでパフォーマンスを向上させることができます。 これを行うには、 シンボル サーバーからこのディレクトリにシンボルをキャッシュするのパスを入力します。 Microsoft パブリック シンボル サーバーに接続するには、この設定を有効にする必要があります。 リモート コンピューター上のプログラムをデバッグしている場合、キャッシュ ディレクトリはリモート コンピューター上のディレクトリを参照することに注意してください。
- OK をクリックします。
- Microsoft パブリック シンボル サーバーを使用しているため、エンド ユーザー ライセンス契約ダイアログ ボックスが表示されます。 はい をクリックして契約に同意し、シンボルをローカル キャッシュにダウンロードします。
WinDbg によるミニダンプのデバッグ
Windows デバッグ ツールの一部であるデバッガーである WinDbg を使用してミニダンプをデバッグすることもできます。 WinDbg を使用すると、Visual Studio を使用せずにデバッグできます。 Windows デバッグ ツールをダウンロードするには、 Windows Hardware Developer Centralの Windows デバッグ ツール を参照してください。
Windows デバッグ ツールをインストールした後、WinDbg にシンボル パスを入力する必要があります。
WinDbgでシンボルパスを入力するには
「ファイル」 メニューで、 「シンボル パス」をクリックします。
シンボル検索パス ウィンドウで、次のように入力します。
"srv\*c:\\cache\*https://msdl.microsoft.com/download/symbols;"
ミニダンプでコピー防止ツールを使用する
開発者は、コピー保護スキームがミニダンプにどのような影響を与えるかについても認識する必要があります。 ほとんどのコピー防止スキームには独自の暗号解除ツールがあり、 MiniDumpWriteDumpでそれらのツールを使用する方法を学ぶのは開発者の責任です。
まとめ
MiniDumpWriteDump 関数は、製品のリリース後にバグを収集して解決する際に非常に便利なツールになります。 MiniDumpWriteDump を使用するカスタム例外ハンドラーを記述することで、開発者は情報収集をカスタマイズし、デバッグ プロセスを改善できます。 この関数は、あらゆる C++ ベースのプロジェクトで使用できるほど柔軟性が高く、あらゆるプロジェクトの安定化プロセスの一部として考慮する必要があります。