• .Net8的异常内存模型长啥样?
  • 发布于 2个月前
  • 229 热度
    0 评论
前言
.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.结果
它这个运行模型如下图所示

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