C++でWindowsのダンプファイル出力を作る


アクセスバイオレーションなどでクラッシュした際、ダンプファイルを出力できると、後々のデバッグやユーザーサポートに役立ちます。Windows には構造化例外処理というものがあり、それを利用することで、クラッシュ時にダンプファイルを生成するようなプログラムを書くことができます。

クラッシュダンプの出力自体は、以下のページを参考に。

ダンプファイルの出力

クラッシュ ダンプの分析ページのソースコードをそのまま掲載。しています。

さて、なぜこのブログを書いたかというと、

 __try 
あたりが、Visual Studio でただ書いただけだとうまくコンパイルが通らないのです。

コンパイル設定を変更

まず、構造化例外処理を使うには、Exe のコンパイル設定を変更する必要があります。

[構成プロパティ] - [C/C++] - [コード生成] - [C++の例外を有効にする] はい - SEH の例外あり (/EHa) に変更します。

これをやっておかないと、なんだかうまく例外をキャッチしてくれません。

コンパイルが通らなくなる

これで、

__try
が動いてくれるのですが、
__try ~ __except
のが複雑になってくると、コンパイラ エラー C2712 が発生するようになってしまいます。正直、これはよくわかりません…

C++ の例外でラッパーする

__try
をやめて、単に C++ の例外で囲めばよいのではないかと思ったのですが、すると、ダンプ生成で欲しい
EXCEPTION_POINTERS
のポインタが取得できません。そこで、調べてみると、C++ での構造化例外の処理という記事があり、これを試してみました。

手順としては以下の通り。

  1. ラッパー用のクラスを定義
  2. 変換関数を書く
  3. _set_se_translator
    で変換関数を登録する

ラッパークラスと変換関数は書いてみるとこんな感じ。

あとは、この例外をキャッチして、メンバの exPointer を GenerateDump に渡せば完了です。この方法なら、先ほどの C2712 も発生しませんでした。

まとめ

ダンプファイルの出力方法をまとめました。ポイントは以下の 3 つ。

  • MiniDumpWriteDump でダンプファイルを作れる
  • 構造化例外処理を有効にするために、コンパイル設定で /EHa に変更する
  • C++ の例外処理に変換する