Jör*_*tag 41
例外只是高级非本地流控制结构的更一般情况的一个具体示例.其他例子是:
GOTO,在高级,高阶语言中流行),GOTO.(我确定我错过了很多其他人.)
这些结构的一个有趣的特性是它们在表达能力上大致相同:如果你有一个,你可以很容易地构建所有其他的.
那么,您如何最好地实现异常取决于您可用的其他构造:
GOTO,因此如果必须的话,你可以随时回归.setjmp/ longjmp基本上是MacGyver延续(用胶带和牙签制成,不是真的,但如果你没有更好的东西,至少会让你摆脱困境).一个非常有趣的使用情况,无论是的使用异常,并在实施例外的是微软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是许多运行时的公共中间表示,因此所描述的机制可以应用于许多语言.
C/C++编译器使用底层OS工具进行异常处理.像.Net或Java这样的框架也在VM中依赖于OS工具.例如,在Windows中,真正繁重的工作是由SEH(结构化异常处理基础架构)完成的.您绝对应该阅读旧的参考文章:关于Win32™结构化异常处理深度的崩溃课程.
至于不使用例外的成本,它们是昂贵的,但与什么相比?与返回错误代码相比?在考虑正确性和代码质量的成本之后,商业应用程序的异常总是会获胜.除了几个非常关键的操作系统级别功能外,总体而言异常总是更好.
最后但并非最不重要的是,使用流程控制异常的反模式.例外情况应该是例外情况,滥用流量控制异常的代码将为性能付出代价.