如何在引擎盖下实施例外?

Ham*_*jan 64 c c++ python exception

几乎每个人都使用它们,但很多人,包括我,只是认为他们只是工作是理所当然的.

我正在寻找高品质的材料.我使用的语言是:Java,C,C#,Python,C++,所以这些对我来说最感兴趣.

现在,C++可能是一个很好的起点,因为你可以用这种语言抛出任何东西.

此外,C接近装配.如何使用纯C结构模拟异常而不使用汇编?

最后,我听到一则传言,由于速度考虑,谷歌员工不会对某些项目使用例外.这只是谣言吗?没有它们,如何才能实现重大成就?

谢谢.

Jör*_*tag 41

例外只是高级非本地流控制结构的更一般情况的一个具体示例.其他例子是:

  • 通知(异常的概括,最初来自一些旧的Lisp对象系统,现在在例如CommonLisp和Ioke中实现),
  • continuation(一种更结构化的形式GOTO,在高级,高阶语言中流行),
  • 协同程序(子程序的推广,尤其在Lua中流行),
  • Python的生成器(基本上是一种限制形式的协同程序),
  • 纤维(合作轻质线)当然已经提到过了
  • GOTO.

(我确定我错过了很多其他人.)

这些结构的一个有趣的特性是它们在表达能力上大致相同:如果你有一个,你可以很容易地构建所有其他的.

那么,您如何最好地实现异常取决于您可用的其他构造:

  • 每个CPU都有GOTO,因此如果必须的话,你可以随时回归.
  • C有setjmp/ longjmp基本上是MacGyver延续(用胶带和牙签制成,不是真的,但如果你没有更好的东西,至少会让你摆脱困境).
  • JVM和CLI有自己的例外,这意味着如果你的语言的异常语义与Java的/ C#匹配,那么你就可以免费回家(但如果没有,那么你就搞砸了).
  • Parrot VM作为例外和延续.
  • Windows有自己的异常处理框架,语言实现者可以使用它来构建自己的异常.

一个非常有趣的使用情况,无论是的使用异常,并实施例外的是微软Live实验室的沃尔特项目.(现已不复存在.)Volta的目标是通过按钮为Web应用程序提供架构重构.因此,您可以将您的单层Web应用程序转换为两层或三层应用程序,只需在.NET代码上添加一些[Browser][DB]属性,然后代码就可以在客户端或数据库中自动运行.为了做到这一点,显然必须将.NET代码翻译成JavaScript源代码.

现在,您可以在JavaScript中编写整个VM并运行未修改的字节码.(基本上,将CLR从C++移植到JavaScript.)实际上有一些项目可以执行此操作(例如HotRuby VM),但这既低效又不能与其他JavaScript代码很好地互操作.

因此,他们编写了一个编译器,将CIL字节码编译为JavaScript源代码.但是,JavaScript缺乏.NET所具有的某些功能(生成器,线程,两个异常模型也不是100%兼容),更重要的是它缺少编译器编写者喜欢的某些功能(无论是GOTO连续还是延续),并且可以用于实现上述缺失的功能.

但是,JavaScript 确实有例外.因此,他们使用JavaScript Exceptions来实现Volta Continuations,然后他们使用Volta Continuations来实现.NET Exceptions,.NET Generators甚至.NET Managed Threads(!!!)

那么,回答你原来的问题:

如何在引擎盖下实施例外?

有了例外,具有讽刺意味!至少在这个非常具体的情况下,无论如何.

另一个很好的例子是Go邮件列表中的一些例外提议,它使用Goroutines实现异常(类似于并发协程和CSP进程的混合).另一个例子是Haskell,它使用Monads,惰性求值,尾调用优化和高阶函数来实现异常.一些现代CPU还支持异常的基本构建块(例如专为Azul Systems Java计算加速器设计的Vega-3 CPU).


Ada*_*ode 22

以下是实现C++异常的常用方法:http:
//www.codesourcery.com/public/cxx-abi/abi-eh.html

它适用于Itanium体系结构,但此处描述的实现也用于其他体系结构.请注意,它是一个很长的文档,因为C++异常很复杂.

以下是有关LLVM如何实现异常的详细说明:http:
//llvm.org/docs/ExceptionHandling.html

由于LLVM是许多运行时的公共中间表示,因此所描述的机制可以应用于许多语言.

  • 第一个链接现在已经破了 (3认同)
  • 两个链接都是很好的参考. (2认同)
  • 第一个链接再次断开。 (2认同)

Eli*_*sky 17

在他的书" C接口和实现:创建可重用软件的技术"中,DR Hanson使用一组宏和一组在纯C中提供了一个很好的异常实现setjmp/longjmp.他提供了TRY/RAISE/EXCEPT/FINALLY宏,可以模拟C++异常所做的一切以及更多.

这里可以仔细阅读代码(查看except.h/except.c).

PS关于谷歌的问题.他们的员工实际上被允许在新代码中使用异常,并且旧代码禁令的官方原因是因为它已经以这种方式编写而且混合样式没有意义.

就个人而言,我也认为没有例外的C++不是最好的主意.


Rem*_*anu 7

C/C++编译器使用底层OS工具进行异常处理.像.Net或Java这样的框架也在VM中依赖于OS工具.例如,在Windows中,真正繁重的工作是由SEH(结构化异常处理基础架构)完成的.您绝对应该阅读旧的参考文章:关于Win32™结构化异常处理深度的崩溃课程.

至于不使用例外的成本,它们是昂贵的,但与什么相比?与返回错误代码相比?在考虑正确性和代码质量的成本之后,商业应用程序的异常总是会获胜.除了几个非常关键的操作系统级别功能外,总体而言异常总是更好.

最后但并非最不重要的是,使用流程控制异常的反模式.例外情况应该是例外情况,滥用流量控制异常的代码将为性能付出代价.

  • 结构化异常与C ++异常不同。 (2认同)
  • C++异常作为SEH实现.需要了解SEH才能理解C++异常. (2认同)
  • 我的意思是在Win32上,显然 (2认同)
  • 顺便说一句,当一个关于例外的问题包含在其标题"引擎盖下"时,将是一个犯罪*而不是*链接到Matt Pietrek的文章...... http://blogs.msdn.com/matt_pietrek/ (2认同)

Nor*_*sey 6

有关异常实施的最佳论文(在幕后)是Barbara Liskov和Alan Snyder 在CLU中异常处理.每次我开始使用新的编译器时我都会提到它.

对于用C实现的稍高级别的观点setjmplongjmp,我建议戴夫·汉森的I2C接口和实现(如伊莱Bendersky).

  • 不,我在一个盒子里有一份纸质副本,或者我可以通过我的大学图书馆获得它.当所有的写作,编辑和裁判都由志愿者完成时,专业协会对重印收取如此巨大的费用这一事实是一个令人遗憾的骗局. (6认同)

Ign*_*ams 5

setjmp()并且longjmp()通常。

异常捕获确实有很大的成本,但对于大多数用途来说,这不是什么大问题。