前言
.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();
结尾
小的细节,记录下
作者:江湖评谈