1

catchキーワードは、スローされた例外のタイプをどのように決定しますか?実行するcatchブロックを選択するためにどのようなプロセスが発生しますか?

try
{
    int[] myArray = new int[0];
    myArray[1] = 0;
}
catch (IndexOutOfRangeException ex) { } // how does the CLR know to enter here?
catch (InvalidCastException ex) { }

ILdasm経由

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       28 (0x1c)
  .maxstack  3
  .locals init (int32[] V_0,
           class [mscorlib]System.IndexOutOfRangeException V_1,
           class [mscorlib]System.InvalidCastException V_2)
  IL_0000:  nop
  .try
  {
    IL_0001:  nop
    IL_0002:  ldc.i4.0
    IL_0003:  newarr     [mscorlib]System.Int32
    IL_0008:  stloc.0
    IL_0009:  ldloc.0
    IL_000a:  ldc.i4.1
    IL_000b:  ldc.i4.0
    IL_000c:  stelem.i4
    IL_000d:  nop
    IL_000e:  leave.s    IL_001a
  }  // end .try
  catch [mscorlib]System.IndexOutOfRangeException 
  {
    IL_0010:  stloc.1
    IL_0011:  nop
    IL_0012:  nop
    IL_0013:  leave.s    IL_001a
  }  // end handler
  catch [mscorlib]System.InvalidCastException 
  {
    IL_0015:  stloc.2
    IL_0016:  nop
    IL_0017:  nop
    IL_0018:  leave.s    IL_001a
  }  // end handler
  IL_001a:  nop
  IL_001b:  ret
 } // end of method Program::Main

catchただし、スローされた例外のタイプを判別するためにキーワードが何を実行するかはまだ明確ではありません。

4

2 に答える 2

12

簡単に言えば、本物には本が必要です。.NETでの例外処理は途方もなく複雑で、多くの可動部分が関係しています。Windowsでの例外のネイティブサポート(SEH、構造化例外処理)、CLRで最大かつ最も複雑なコードチャンクの1つ(excep.cpp、232KBのコード)、アセンブリ内のメタデータ(これが、あなたがしない理由です)を含みます。 ILアドレスを取得していることを確認してください)とジッター。

例外はスローによって発生しますキーワードを指定すると、実行時にRaiseException()WindowsAPI関数がトリガーされます。Windowsは、RtlAddFunctionTable()によって登録された例外フィルターを実行することにより、例外を処理できるコードを探します。これはCLRに実装されています。次に、ジッターによって生成されたメタデータ、ジッターがILをマシンコードに変換するジャストインタイムのコンパイル時に作成されるデータのテーブルを使用します。ジッタは、逆アセンブリで表示される.tryやcatchなどのディレクティブによってアセンブリメタデータに追加されたメタデータ情報を使用します。テーブルデータには、特定の例外タイプのcatch句を表すコードの範囲に関する情報が含まれています。CLRが実行を再開する場所を選択し、Windowsに例外の処理を続行するように指示できるようにします。

Windowsは、開始場所と停止場所を認識して、スタックフレームの巻き戻しを開始し、必要に応じてfinallyブロックを呼び出します。次に、catchブロックの最初のマシンコード命令に設定した命令ポインタ。

これを超えてたくさんの厄介な小さな詳細。ThreadAbortExceptionのセマンティクスと同様に、vb.net Catch Whenキーワードは、finallyブロックで例外を発生させ、SEHが純粋にスタックフレームベースの場合はtryブロックスコープを処理し、スレッドを中止する必要がある場合はキャッチできない例外の概念を扱います。読者がすぐに眠りに落ちるので、本を取るが誰もそれを書くことは決してないもの。

.NETでの例外処理は、鉛で満たされた氷山です。99%は水中にあり、CLRで最も成功した抽象化の1つです。プログラマーがcatchキーワードを頻繁に使用することを除けば、それは実装方法とは何の関係もありません。

于 2012-09-05T21:12:09.820 に答える
2

免責事項:CLRの仕様を読んだことがなく、例外が「通常の」コードよりもはるかに複雑であることを知っています。ただし、これは非常に単純なアプローチであり、うまくいくと思います。

  1. 例外がスローされると、それを生成するコードは、ベースIndexOutOfBoundsなどの特定のタイプを使用します。HttpExceptionException
  2. ブロック内で例外がキャッチされるtryと、ランタイムには予想されるタイプの例外のリストが表示されます(つまり、ブロックごとに1つcatch)。それがList<Type> TheseExceptionsMayOccur
  3. 最後に、それは次のようなものになります

foreach(Type ExceptionType in TheseExceptionMayOccur)
{
    if(e is ExceptionType )
        //run the respective catch block
}
于 2012-09-05T20:23:57.787 に答える