Visual C++異常処理メカニズムの原理と応用(五)——C/C++構造化異常処理のtry-except異常処理の使用(下)

2628 ワード

前述の記事では,VC++構造化異常処理に関する内容を紹介したが,現在はアクセス違反,除数0などの異常がコードに本来存在する異常をキャプチャする用途に限られている.実際には、多くの場合、このメカニズムを完全に利用して、異常をトリガーし、実行プロセスを異常処理段階に移行させることもできます.
最も典型的な例は、Windowsでヒープの作成やヒープメモリの割り当てに使用されるHeapCreateやHeapAllocなどの関数であり、転送されたdwFlagsにHEAP_が追加された場合GENERATE_EXCEPTIONSタグは、割り当てまたは作成に失敗した場合、これらの関数は他のWinAPIのように戻り値ではなく、直接例外を放出します.この場合、それらを呼び出すコードも、APIを呼び出すたびに戻り値をチェックする必要はなく、tryブロックに通常呼び出しの実行フローを書き込み、exceptブロックに異常処理のコードを書き込む.これにより、以前の各WinAPIの後のif判定が成功したか否かの文が省略され、exceptに集約され、プログラムの通常の実行フローがより簡単になる.このような私たち自身が投げ出した異常を「ソフトウェア異常」と呼ぶ.
Win 32 APIでは、RaiseException関数を使用して例外を放出します.プロトタイプは次のとおりです.
void WINAPI RaiseException(
__in DWORD dwExceptionCode,
__in DWORD dwExceptionFlags,
__in DWORD nNumberOfArguments,
__in const ULONG_PTR *lpArguments );

ここで、
  • 最初のパラメータExceptionCodeは、C/C++構造化異常処理でGetExceptionCode()インライン関数を使用して取得してもよいし、GetExceptionInformationを使用してExceptionPointers構造を取得してもよいし、その中のExceptionRecordメンバーのExceptionCodeフィールドを使用して取得してもよい.なお、この2つのインライン関数は、異常処理中のフィルタ関数部分でのみ呼び出され、他の場合では使用できない.したがって、他の場所で使用する必要がある場合は、フィルタ関数でコピーし、その後、このコピーのコピーを使用する必要があります.(VCの異常処理メカニズムがスタックに構築するため)
  • 第2パラメータExceptionFlagsは、異常が実行を継続できるかどうかを指定し、0が入力された場合、エラーのコマンドを実行し続けることができることを示す.EXCEPTION_が転送された場合NONCONTIONUABLEは,対応する異常処理中にユーザがその命令を再実行することを選択できることを示す.
  • 第3、4のパラメータは、それぞれ、追加情報を送信する個数および配列ヘッダアドレスに使用され、その送信する追加パラメータの個数は15を超えてはならない.

  • WindowsシステムのRing 3階層構造化例外処理メカニズムを理解すると、これらの入力パラメータは例外処理関数の最初のパラメータであるEXCEPTION_であることが容易にわかります.RECORD構造のメンバー.この構造は次のように定義されます.
    typedef struct _EXCEPTION_RECORD {
      DWORD                    ExceptionCode;
      DWORD                    ExceptionFlags;
      struct _EXCEPTION_RECORD  *ExceptionRecord;
      PVOID                    ExceptionAddress;
      DWORD                    NumberParameters;
      ULONG_PTR                ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
    } EXCEPTION_RECORD, *PEXCEPTION_RECORD;

    最初の2つと最後の2つのパラメータは、ここでRaiseExceptionが入力したパラメータです.中間の2つは、簡単に説明します.
    ExceptionRecordフィールドはネストされた例外処理に使用されます.つまり、ある例外の処理中にまた新しい例外が発生した場合、システムはまず新しい例外に対応するEXCEPTION_を返します.RECORD構造で、ExceptionRecordフィールドで古い例外を指します.したがって、ネスト例外が発生すると、このフィールドはチェーンを形成します.
    ExceptionAddressフィールドは、例外を引き起こす文のアドレスです.
    実は今私達はすでに一歩一歩C/C++の構造化異常処理からWindowsシステムRing 3級の構造化異常処理に向かって、C/C++の構造化異常処理はWindowsシステムRing 3級の構造化異常処理メカニズムを利用した.C/C++の構造化異常処理の機構と原理をより良く解析するために.後続記事では,WindowsシステムRing 3クラスの構造化異常処理について比較的包括的に紹介する.