プログラムを書こう!

実務や自作アプリ開発で習得した役に立つソフトウェア技術情報を発信するブログ

Win32APIでトップレベルの例外を捕捉する。

この記事は2019年03月10日に投稿しました。

f:id:paveway:20190914064630j:plain

目次

  1. はじめに
  2. Win32APIでトップレベルの例外を捕捉する
  3. おわりに

猫でもわかるWindowsプログラミング 第4版 猫でもわかるシリーズ

猫でもわかるWindowsプログラミング 第4版 猫でもわかるシリーズ

1. はじめに

こんにちは、iOSのエディタアプリPWEditorの開発者の二俣です。
今回は業務で使用しているWin32APIでトップレベルの例外を捕捉する方法についてです。

目次へ

2. Win32APIでトップレベルの例外を捕捉する

Win32APIでトップレベルの例外を捕捉する方法ですが、Win32APIにSetUnhandledExceptionFilter関数を使用して行います。

トップレベルの例外とは何かはっきりしないのですが、NULLアクセス0除算などを意味しているようです。

トップレベルの例外が発生すると、デフォルトの例外ハンドラが呼び出されます。
そのデフォルトの例外ハンドラをSetUnhandledExceptionFilter関数によって、ユーザ定義の例外ハンドラに置き換えることができます。

注意

サンプルアプリで動作検証しましたが、意図通りに動作しませんでいた。
フォームアプリでボタンを押下した時に0除算で例外を発生させて、例外ハンドラが呼び出されるのを確認しようとしました。
しかし呼び出される時と呼び出されないときがありました。

  • 呼び出される時

    • デバッグ版でビルドした時
    • 例外発生時、標準のエラーダイアログが表示されますが、エラーダイアログの"再試行"ボタンを押下した時
  • 呼び出されない時

    • デバック版でビルドして、エラーダイアログの"再試行"ボタン以外のボタン(中止ボタン、無視ボタン)を押下した時
    • リリース版でビルドした時

書式

LPTOP_LEVEL_EXCEPTION_FILTER WINAPI SetUnhandledExceptionFilter(_IN_ LPTOP_LEVEL_EXCEPTION_FILTER lpTopLevelExceptionFilter);

引数

lpTopLevelExceptionFilter
トップレベルの例外フィルタ関数へのポインタ
例外フィルタ関数は

LONG WINAPI <関数名>(EXCEPTION_POINTERS* pExceptionInfo);

の書式に合わせます。

戻り値は以下を指定します。

戻り値(値) 内容
EXCEPTION_EXECUTE_HANDLER(0x1) UnhandledExceptionFilterから戻り 、関連付けられている例外ハンドラを実行します。
これは通常プロセスの終了につながります。
EXCEPTION_CONTINUE_EXECUTION(-1) UnhandledExceptionFilterから戻り 、例外の箇所から実行を続けます。
LPEXCEPTION_POINTERSパラメータを通じて提供される例外情報を変更することによって、フィルタ関数は継続状態を自由に変更できることに注意してください。
EXCEPTION_CONTINUE_SEARCH(0x0) UnhandledExceptionFilterを通常通り実行します。
これは、SetErrorModeフラグに従うこと、またはApplication Errorポップアップメッセージボックスを呼び出すことを意味し ます。

戻り値

成功した場合、前の例外フィルタ関数へのポインタアドレスを返却します。
失敗した場合、NULLが返却されます。

実装例

Sample.h

class CSampleApp : public CWinApp
{
...
private:
    static LONG WINAPI TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionInfo);
...
}

Sample.cpp

/**
 * @brief コンストラクタ
 */
CSampleApp::CSampleApp()
{
   ...
   // ユーザ定義の例外ハンドラを設定します。
   SetUnhandledExceptionFilter(&CSampleApp::TopLevelExceptionFilter);
   ...
}

/**
 * @brief ユーザ定義の例外ハンドラ
 *
 * @return 
 */
LONG CSampleApp::TopLevelExceptionFilter(EXCEPTION_POINTERS* pExceptionInfo)
{
    AfxMessageBox(_T("致命的なエラーが発生しました。"));
    return EXCEPTION_EXECUTE_HANDLER;
}

目次へ

3. おわりに

業務アプリの例外処理について調査した時にこの方法を見つけました。
リリース版で動作しない(動作させるやり方がわからない)ので、今のところ使えない感じです。

【LITALICOワンダー】

Win32 APIオフィシャルリファレンス改訂3版 Windowsサービス/ネットワーク編 (Ascii books)

Win32 APIオフィシャルリファレンス改訂3版 Windowsサービス/ネットワーク編 (Ascii books)

紹介している一部の記事のコードはGitlabで公開しています。
興味のある方は覗いてみてください。

目次へ


私が勤務しているニューラルでは、主に組み込み系ソフトの開発を行っております。
弊社製品のハイブリッドOS Bi-OSは高い技術力を評価されており、特に制御系や通信系を得意としています。
私自身はiOSモバイルアプリウィンドウズアプリを得意としております。
ソフトウェア開発に関して相談などございましたら、お気軽にご連絡ください。

また一緒に働きたい技術者の方も随時募集中です。
興味がありましたらご連絡ください。

EMAIL : info-nr@newral.co.jp / m-futamata@newral.co.jp
TEL : 042-523-3663
FAX : 042-540-1688

目次へ