我一直在想:臭名昭着的VB.NET語句「On Error Resume Next」如何轉換爲CIL?它涉及包裝每一行嘗試......捕獲?CIL執行On Error Resume Next
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();
}
}
從
除了事實上,它使用了一堆開關和gotos,我不知道該代碼實際上做了什麼。
相關問題
- 1. Application.OnTime on Error Resume Next
- 2. VBA:Err.Clear,Resume,Resume Next不會阻止On Error GoTo從只執行一次
- 3. Visual Basic的On Error Resume Next for C++?
- 4. C#On Error resume
- 5. 「On Error Resume Next」語句的作用是什麼?
- 6. FireBug 1.7.3 - 關閉Break On Next,改爲Break On Error?
- 7. C printf term progress display with error messages on next line
- 8. On Error Goto引發錯誤
- 9. vbscrip error set on OpenTextFile()
- 10. Titanium「resume」event not unlock on unlock(iphone)
- 11. On Error not in vba
- 12. DSC Abort on Error
- 13. SIGBART on UIApplicationMain error
- 14. mod_rewrite on 403 error
- 15. .resume在調用其他委託方法後執行
- 16. 如何使用On Error GoTo?
- 17. ActiveRecord :: StatementInvalid:Timeout :: Error:執行過期
- 18. On Error Goto in Python
- 19. ruby on rails rspec error
- 20. setOnClickListener FloatingActionButton on Fragment Error
- 21. linphone on windows building error
- 22. SoapUI error on request - NoClassDefFoundError
- 23. Ruby on Rails | AirBrake Error
- 24. Redmine pg error on heroku
- 25. RewriteEngine on casuses error 500
- 26. SKPhysicsbody error on collision swift
- 27. On Error轉到0不重置錯誤陷印
- 28. VbScript錯誤對象通過On Error Statement清除
- 29. 登錄Activity,postOnExecute,Resume
- 30. Javascript Error,Escaping Problem,Grid not working,Error on Firebug