gpt4 book ai didi

.net - 为什么在 .NET 异常处理期间保存所有寄存器?

转载 作者:行者123 更新时间:2023-12-02 15:49:53 25 4
gpt4 key购买 nike

至少根据 Mono's exception handling implementation 的描述,当抛出异常时,所有 x86 寄存器都会被保存。除了堆栈指针(ESP)、帧指针(EBP)、指令指针(EIP)和保存异常对象的寄存器之外,为什么还保存其他寄存器?为什么要保存整个上下文,而在 .NET 中没有机制可以在抛出后立即继续执行?

更新:

EMCA 在第 12.3.2.4 节异常处理概述中规定了以下内容:

  • 描述异常的异常对象由 CLI 自动创建并推送到计算堆栈作为过滤器或 catch 子句输入时的第一项。

  • 除非使用过滤器处理程序,否则无法在异常位置恢复执行。

我不知道如何根据前面的陈述来完成“除了使用过滤器处理程序”。此外,endfilter 操作码的描述只有两个结果:“继续搜索另一个异常处理程序”或执行该处理程序(这将执行另一个 CIL 操作码 block )。它缺少“恢复”选项。因此,我将规范中的这种差异解释为基本上意味着 .NET 不支持在抛出后立即继续执行。也许在某个时候考虑过但从未完全实现和实现。

更新2:

有人指出,如果没有过滤器处理程序选择捕获异常,则可能会发生“恢复”。然而, throw 的规范指出:“throw 指令将异常对象抛出到堆栈上并清空堆栈。”清空堆栈将导致无法在 throw 语句之后立即执行代码,因为该代码可能需要堆栈上的某些内容。

最佳答案

您正在查看实现细节:由于许多可能的原因(例如易于实现、代码共享、提供额外的语义、面向 future 、优化等),它们通常与 ECMA 规范不是一对一的匹配。

在这种特殊情况下,有几个考虑因素。

Mono 基于称为 MonoContext 的处理器状态 View 执行异常处理:由于此结构也在其他地方使用,因此它包含所有相关寄存器,即使在某些特定情况下可能不需要某些寄存器。特别是,异常处理也可以从CPU异常开始,所有寄存器都需要恢复,所以所有寄存器都被收集。

有人已经观察到上下文也用于调试器。

还请考虑带有 try/catch 的方法的情况,其中 catch 是一个简单的本地 var 设置。现在,高级寄存器分配器可能会在 throw 之前(注意 throw 可能是隐式的,如空引用,因此由 cpu 异常路径处理)和 catch 之后放置在像 edx 这样的寄存器中使用的本地 var。如果您不保存抛出/异常点处的所有寄存器,则会破坏程序状态,因为 edx 在异常处理期间会被覆盖。

最后评论:您是否担心保存几个额外的寄存器会浪费 CPU 周期?如果您实际计算所花费的周期,它们完全处于异常处理期间需要发生的所有事情的噪音中。

关于.net - 为什么在 .NET 异常处理期间保存所有寄存器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8552755/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com