首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >C#中的异常处理是否与ECMA-335标准相矛盾?

C#中的异常处理是否与ECMA-335标准相矛盾?
EN

Stack Overflow用户
提问于 2012-08-28 23:10:45
回答 3查看 571关注 0票数 23

我的理解是基于这篇很长但很棒的文章,它支持C#规范中列出的行为。

CLI标准(EMCA-335)表明,如果没有合适的捕获,运行时应该立即终止。.NET运行时没有这样做,相反,它似乎倾向于C#规范(EMCA-334)的行为。

首先,我觉得奇怪的是,语言规范似乎定义了框架行为。第二,它们似乎自相矛盾。

  • 他们是自相矛盾,还是我搞错了文件的意思?
  • 运行时必须以这种方式进行异常处理才能符合标准吗?

作为一个可选的问题,哪一个是“正确的”问题,比如,如果我要编写我自己的CLI实现,我应该使用哪一个?注意,EMCA-335 (CLI)文档是两个月前更新的,其中EMCA-334 (C#)是在2006年更新的。

ECMA-335分区I节12.4.2.5

  • 当发生异常时,CLI将在数组中搜索的第一个受保护块。
    • 保护一个区域,包括当前指令指针和
    • 是catch处理程序块,并且
    • 其筛选器希望处理异常。

  • 如果在当前方法中找不到匹配,则搜索调用方法,以此类推。如果没有找到匹配项,CLI将转储堆栈跟踪并中止程序。
  • 如果找到匹配,则CLI将堆栈送回刚才定位的点,但这次调用finally和故障处理程序。然后启动相应的异常处理程序。

C#规范第15.9.5和15.10节 (关于MSDN的§8.9.5和§8.10)

它与CLI标准的主要区别在于,无论是否找到了catch块,应用程序不仅存在,而且仍然会展开堆栈,并处理最后的处理程序。

我建议阅读标准本身,以获得更好的含义,因为以下是一个非常粗略的总结。它一步一步地概述了如何在每个可能的场景中执行try语句。

  • 在引发异常的函数中:
    • 在每个try语句中寻找匹配的catch子句
      • 如果catch语句存在,则执行它。

代码语言:javascript
代码运行次数:0
运行
复制
- A finally block is executed if it exists

  • 如果没有处理程序,则在调用函数中重复上述步骤。
  • 如果异常处理终止当前线程中的所有函数成员调用(指示线程没有异常处理程序),则线程本身将终止。这种终止的影响是由执行定义的。
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-08-29 00:26:28

我认为这可能只是一个含糊的措辞问题。

如果在当前方法中找不到匹配,则搜索调用方法,以此类推。如果没有找到匹配项,CLI将转储堆栈跟踪并中止程序。

好吧,在C#中是这样的。我们都知道,如果我们没有一个catch,那么一个异常将使我们的程序瘫痪。

如果找到匹配,则CLI将堆栈送回刚才定位的点,但这次调用finally和故障处理程序。然后启动相应的异常处理程序。

这也符合我们对C#的了解。如果有一些finally (我们没有看到fault)块,当我们从抛出的异常上升到catch块时,这些块将被处理,但是它们会在那里停止,不会在堆栈上继续运行。

很大程度上取决于我们如何阅读“如果”,它开始了我刚才引用的第二节。你读起来就像“如果.那么.否则就不会有这样的事情了”。但是,它可以读为识别堆栈中将被移动到的点的第一个摘录:如果有一个catch,那么它已经走到了那个点。如果没有捕获,那么它就会走到堆栈的最顶端,然后我们得到一个转储和中止。最终处理程序(和故障处理程序)仍然被调用,但重点不是匹配的catch处理程序。

你的阅读是最直截了当的,而我的则是把事情拉得有点长的。然而,在同一标准的其他地方,我的描述与finally的描述非常接近。

票数 3
EN

Stack Overflow用户

发布于 2012-08-29 00:13:33

这里没有冲突。C#语言规范的措辞如下:

如果try语句没有catch子句,或者没有catch子句匹配异常: 如果try语句有一个finally块,那么执行finally块。 异常被传播到下一个包含try语句的容器中。

这里的项目2没有特别说明在没有下一个包含try语句的情况下会发生什么。为此,请转到8.9.5结尾:

如果异常处理终止当前线程中的所有函数成员调用(指示线程没有异常处理程序),则线程本身将终止。这种终止的影响是由执行定义的。

当然,它是由实现定义的。除了Ecma 335规范之外,异常处理策略是Microsoft中的一个可配置项。由ICLRPolicyManager::SetActionOnFailure()控制。然后,使用<legacyUnhandledExceptionPolicy> app.exe.config文件元素在默认主机中进行配置。CLRVersion2.0和更高版本的默认设置是立即终止程序。

否则,这是相当无效的圣经解释学。所有这些都不应该让C#程序员感到惊讶,特别是考虑到测试是多么容易。

票数 5
EN

Stack Overflow用户

发布于 2012-08-29 02:38:04

O.P.中的被引用文章有一个错误的基本假设:

当然,如果不首先考虑Windows结构化异常处理(SEH),我们就不能谈论托管异常。我们还需要查看C++异常模型。这是因为托管异常和C++异常都是在底层SEH机制之上实现的,而且托管异常必须与SEH和C++异常互操作。

CLR标准(ISO 23271/ECMA 335)有意与平台无关。Microsoft的实现是许多可能的实现之一(当然,Mono是另一个实现)。

我敢肯定,与Windows结构化异常处理和C++异常处理的互操作性是微软的选择,而不是ISO 23271的要求。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12168825

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档