私はいつも不思議だった:悪名高いVB.NETステートメント "On Error Resume Next"はどのようにCILに変換されたのですか?それはtry ... catchesですべての行を折り返しますか?オンエラー再開のCIL実装
2
A
答えて
3
後藤。
try-catchと従来のエラー処理を組み合わせることはできません。 On Error Resume Next
を使用すると、メソッド内のすべてのコード行に一意の識別子と同様にラベルが付けられます。擬似C#コード:
int currentId = 0;
Label1:
currentId = 1;
Line1();
Label2:
currentId = 2;
Line2();
Label3:
currentId = 3;
Line3();
Exit:
全体のメソッドがtry catchでラップされます。例外がヒットした場合、キャッチハンドラはcurrentId
をチェックし、次のラベルの行に簡単にgoto
を実行します(ProjectError
が設定されています)。
try
{
...
}
catch (Exception ex)
{
ProjectData.SetProjectError(ex);
if (currentId == 1) goto Label2;
if (currentId == 2) goto Label3;
if (currentId == 3) goto Exit;
}
マインドあなたは、これは私が逆コンパイルVB.NETアプリケーションによって得ただけで、実装の詳細は次のとおりです。私たちの場合は、次のようになります。唯一の契約上の動作は、On Error Resume Next
で定義されたものです。これは、基本的に「プロジェクトエラーを設定して次のステートメントに進む」ことです。
0
ここに行く:
Public Sub A()
End Sub
Public Sub B()
End Sub
Public Sub C()
End Sub
Public Sub D()
End Sub
Public Sub E()
End Sub
Public Sub Test()
A()
On Error GoTo ErrorHandler
B()
Exit Sub
C()
ErrorHandler:
D()
Resume Next
E()
End Sub
は(補足的方法なし)にコンパイル:
.method public static void Test() cil managed
{
// Code size 201 (0xc9)
.maxstack 3
.locals init (int32 V_0,
int32 V_1,
int32 V_2)
IL_0000: ldc.i4.1
IL_0001: stloc.2
IL_0002: call void VBTest.Program::A()
IL_0007: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
IL_000c: ldc.i4.2
IL_000d: stloc.0
IL_000e: ldc.i4.3
IL_000f: stloc.2
IL_0010: call void VBTest.Program::B()
IL_0015: leave IL_00c0
IL_001a: ldc.i4.5
IL_001b: stloc.2
IL_001c: call void VBTest.Program::C()
IL_0021: ldc.i4.6
IL_0022: stloc.2
IL_0023: call void VBTest.Program::D()
IL_0028: ldc.i4.7
IL_0029: stloc.2
IL_002a: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
IL_002f: ldloc.1
IL_0030: brtrue.s IL_0047
IL_0032: ldc.i4 0x800a0014
IL_0037: call class [mscorlib]System.Exception [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::CreateProjectError(int32)
IL_003c: throw
IL_003d: ldc.i4.s 9
IL_003f: stloc.2
IL_0040: call void VBTest.Program::E()
IL_0045: leave.s IL_00c0
IL_0047: ldloc.1
IL_0048: ldc.i4.1
IL_0049: add
IL_004a: ldc.i4.0
IL_004b: stloc.1
IL_004c: switch (
IL_007d,
IL_0000,
IL_0007,
IL_000e,
IL_0015,
IL_001a,
IL_0021,
IL_0028,
IL_003d,
IL_003d,
IL_0045)
IL_007d: leave.s IL_00b5
IL_007f: ldloc.2
IL_0080: stloc.1
IL_0081: ldloc.0
IL_0082: switch (
IL_0093,
IL_0047,
IL_0021)
IL_0093: leave.s IL_00b5
IL_0095: isinst [mscorlib]System.Exception
IL_009a: ldnull
IL_009b: cgt.un
IL_009d: ldloc.0
IL_009e: ldc.i4.0
IL_009f: cgt.un
IL_00a1: and
IL_00a2: ldloc.1
IL_00a3: ldc.i4.0
IL_00a4: ceq
IL_00a6: and
IL_00a7: endfilter
IL_00a9: castclass [mscorlib]System.Exception
IL_00ae: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::SetProjectError(class [mscorlib]System.Exception)
IL_00b3: leave.s IL_007f
IL_00b5: ldc.i4 0x800a0033
.try IL_0000 to IL_0095 filter IL_0095 handler IL_00a9 to IL_00b5
IL_00ba: call class [mscorlib]System.Exception [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::CreateProjectError(int32)
IL_00bf: throw
IL_00c0: ldloc.1
IL_00c1: brfalse.s IL_00c8
IL_00c3: call void [Microsoft.VisualBasic]Microsoft.VisualBasic.CompilerServices.ProjectData::ClearProjectError()
IL_00c8: ret
} // end of method Program::Test
このabberationはこれに反射して逆コンパイルされます:脇から
public static void Test()
{
int num2;
try
{
int num3;
Label_0000:
num3 = 1;
A();
Label_0007:
ProjectData.ClearProjectError();
int num = 2;
Label_000E:
num3 = 3;
B();
goto Label_00C0;
Label_001A:
num3 = 5;
C();
Label_0021:
num3 = 6;
D();
Label_0028:
num3 = 7;
ProjectData.ClearProjectError();
if (num2 != 0)
{
goto Label_0047;
}
throw ProjectData.CreateProjectError(-2146828268);
Label_003D:
num3 = 9;
E();
goto Label_00C0;
Label_0047:
num2 = 0;
switch ((num2 + 1))
{
case 1:
goto Label_0000;
case 2:
goto Label_0007;
case 3:
goto Label_000E;
case 4:
case 10:
goto Label_00C0;
case 5:
goto Label_001A;
case 6:
goto Label_0021;
case 7:
goto Label_0028;
case 8:
case 9:
goto Label_003D;
default:
goto Label_00B5;
}
Label_007F:
num2 = num3;
switch (num)
{
case 0:
goto Label_00B5;
case 1:
goto Label_0047;
case 2:
goto Label_0021;
}
}
catch (object obj1) when (?)
{
ProjectData.SetProjectError((Exception) obj1);
goto Label_007F;
}
Label_00B5:
throw ProjectData.CreateProjectError(-2146828237);
Label_00C0:
if (num2 != 0)
{
ProjectData.ClearProjectError();
}
}
実際にはたくさんのスイッチやヒートポンを使用していることから、そのコードが実際に何をしているのかわかりません。
関連する問題
- 1. ワーカースレッドの中断/再開の実装
- 2. mkpasswdの再実装
- 3. 再実装resizeEventは()
- 4. DWC3 USBコントローラでUSBランタイムのサスペンドと再開の実装
- 5. CILでtryブロックについてはCIL
- 6. 再来のapplyMiddlewareの実装
- 7. CIL(MSIL)のStringbuilder
- 8. 再帰スキームのライブラリ実装
- 9. メソッドの再帰的実装
- 10. ハッシュテーブルの実装(再ハッシュスコープエラー)
- 11. アプリケーションの拡張/再実装
- 12. CILのnopのポイント
- 13. Android開発のJPA実装
- 14. インライン展開の実装
- 15. Qt再実装関数
- 16. .NET CILコードサイズ
- 17. 未実装:DSA公開鍵
- 18. カーブの再構成の実装
- 19. HaskellでのLCMの再帰的実装
- 20. python3クラスメソッドへの再帰の実装
- 21. HTTPアップロードの再開を実装する最良の方法の提案
- 22. CILでは「auto」、「ansi」、「cil managed」は何をしますか?
- 23. ファイルストリーム転送での停止と再開の実装 - 方法C#.NET
- 24. 「ToneMatrix」オーディオおもちゃの再実装
- 25. Qt:QGroupBoxのdropEvent()を再実装する
- 26. プリミティブ型を返すメソッドの再実装
- 27. Java - 再帰的リンクリストの実装
- 28. AOSP強制再起動の実装
- 29. Unityランナーゲームのオブジェクトプーリング実装(再利用)
- 30. CIL/MSILボクシングの問題?