.Net8的异常内存模型长啥样?

前言

.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:  nop    IL_000d:  newobj     instance void [System.Runtime]System.Exception::.ctor()    IL_0012:  throw  }  // end .try  catch [System.Runtime]System.Object   {    IL_0013:  pop    IL_0014:  nop    IL_0015:  ldstr      "Into Catch"    IL_001a:  call       void [System.Console]System.Console::WriteLine(string)    IL_001f:  nop    IL_0020:  nop    IL_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,7FFF50A17DC0h  00007FFF50B24423 E8 A8 6E A0 5F       call        CORINFO_HELP_NEWSFAST (07FFFB052B2D0h)  00007FFF50B24428 48 89 45 38          mov         qword ptr [rbp+38h],rax  00007FFF50B2442C 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        00007FFFB04C55B0  00007FFF50B2443E CC                   int         3  00007FFF50B2443F E8 E4 79 E7 FF       call        CLRStub[MethodDescPrestub]@7fff5099be28 (07FFF5099BE28h)  00007FFF50B24444 48 89 45 28          mov         qword ptr [rbp+28h],rax  00007FFF50B24448 90                   nop  00007FFF50B24449 90                   nop  00007FFF50B2444A 48 8D 65 50          lea         rsp,[rbp+50h]  00007FFF50B2444E 5E                   pop         rsi  00007FFF50B2444F 5F                   pop         rdi  00007FFF50B24450 5D                   pop         rbp  00007FFF50B24451 C3                   ret  

4.结果

它这个运行模型如下图所示

.Net8的异常内存模型长啥样?

要点在Catch块执行完成之后,它会执行到Main函数的结尾,也就是最后一个大括号。但是Catch块外面的Console.ReadLine();则没有被执行。当他大括号执行完成之后,才会执行Console.ReadLine();。然后又在执行了一遍大括号。

也就是说:Catch被提取出来了,重新成为了一个函数。类似于以下这种形式。

static void Main(string[] args){  try();  Catch();}Catch(){}Console.ReadLine();

结尾

小的细节,记录下
作者:江湖评谈