前言
.Net8目前到了PreView3这个版本,又㕛叒叕性能提升了,又㕛叒叕搞了很多特性,又㕛叒叕更新了很多东西。然并卵?本篇只看下比较常用的异常。.
概括
1.代码示例:
.Net8的异常内存模型长的比较特殊,不知道之前的6,7是否这样,比如有以下代码:
static void Main(string[] args){int i;int j;int k;Console.WriteLine("test");try{hrow new Exception();}catch{Console.WriteLine("Into Catch");}Console.ReadLine();}
2.IL代码
这段代码是比较简单的一段代码,try里面报了个异常,然后catch把这个异常给吞了。
在IL层面这段代码与源码并无二致
.try{IL_000c: nopIL_000d: newobj instance void [System.Runtime]System.Exception::.ctor()IL_0012: throw} // end .trycatch [System.Runtime]System.Object{IL_0013: popIL_0014: nopIL_0015: ldstr "Into Catch"IL_001a: call void [System.Console]System.Console::WriteLine(string)IL_001f: nopIL_0020: nopIL_0021: leave.s IL_0023} // end handler
3.机器码
机器码层面就开始变异了,它不是按顺序执行的
下面这段代码主要是try块的机器码。里面报了异常之后调用IL_Throw,跳转到Windows下的SEH系统异常进行分派。后者会获取Catch块的地址,当然了Catch块的地址建立在EHInfo上的然后跳转执行。
00007FFF50B24419 48 B9 C0 7D A1 50 FF 7F 00 00 mov rcx,7FFF50A17DC0h00007FFF50B24423 E8 A8 6E A0 5F call CORINFO_HELP_NEWSFAST (07FFFB052B2D0h)00007FFF50B24428 48 89 45 38 mov qword ptr [rbp+38h],rax00007FFF50B2442C 48 8B 4D 38 mov rcx,qword ptr [rbp+38h]00007FFF50B24430 E8 73 49 E5 FF call CLRStub[MethodDescPrestub]@7fff50978da8 (07FFF50978DA8h)00007FFF50B24435 48 8B 4D 38 mov rcx,qword ptr [rbp+38h]00007FFF50B24439 E8 72 11 9A 5F call 00007FFFB04C55B000007FFF50B2443E CC int 300007FFF50B2443F E8 E4 79 E7 FF call CLRStub[MethodDescPrestub]@7fff5099be28 (07FFF5099BE28h)00007FFF50B24444 48 89 45 28 mov qword ptr [rbp+28h],rax00007FFF50B24448 90 nop00007FFF50B24449 90 nop00007FFF50B2444A 48 8D 65 50 lea rsp,[rbp+50h]00007FFF50B2444E 5E pop rsi00007FFF50B2444F 5F pop rdi00007FFF50B24450 5D pop rbp00007FFF50B24451 C3 ret
4.结果
它这个运行模型如下图所示

要点在Catch块执行完成之后,它会执行到Main函数的结尾,也就是最后一个大括号。但是Catch块外面的Console.ReadLine();则没有被执行。当他大括号执行完成之后,才会执行Console.ReadLine();。然后又在执行了一遍大括号。
也就是说:Catch被提取出来了,重新成为了一个函数。类似于以下这种形式。
static void Main(string[] args){try();Catch();}Catch(){}Console.ReadLine();
结尾
小的细节,记录下
作者:江湖评谈