几乎每个人都使用它们,但是许多人,包括我在内,只是想当然地认为它们可以正常工作。
我正在寻找高质量的资料。我使用的语言有: Java、C、C#、Python、C++,所以这些对我来说最感兴趣。
现在,由于你可以在 C++ 中投入任何东西,所以它可能是一个很好的起点。
此外,C 语言接近汇编语言。如何使用纯 C 结构和没有汇编语言来模拟异常?
最后,我听说谷歌员工在某些项目中不使用异常,因为速度考虑。这只是传言吗?如果没有异常,如何完成任何实质性的工作?
谢谢。
几乎每个人都使用它们,但是许多人,包括我在内,只是想当然地认为它们可以正常工作。
我正在寻找高质量的资料。我使用的语言有: Java、C、C#、Python、C++,所以这些对我来说最感兴趣。
现在,由于你可以在 C++ 中投入任何东西,所以它可能是一个很好的起点。
此外,C 语言接近汇编语言。如何使用纯 C 结构和没有汇编语言来模拟异常?
最后,我听说谷歌员工在某些项目中不使用异常,因为速度考虑。这只是传言吗?如果没有异常,如何完成任何实质性的工作?
谢谢。
异常只是更一般的高级非局部流程控制结构的一个具体例子。其他例子包括:
GOTO
形式,在高级、高阶语言中广泛使用),GOTO
。(我相信还有许多我错过的例子。)
这些结构的一个有趣的特性是它们在表达能力方面大致等价:如果你拥有其中的任何一个,你就可以很容易地构建出其他所有结构。
因此,如何最好地实现异常取决于您可用的其他结构:
GOTO
,因此如果必须的话,您总是可以退回到那里。setjmp
/longjmp
,它们基本上是MacGyver的continuations(用胶带和牙签构建的,不是真正的东西,但至少可以在您没有更好选择的情况下让您摆脱眼前的麻烦)。另一个很好的例子是Go邮件列表上关于异常提案,它使用Goroutines来实现异常(类似于并发协程和CSP进程混合的东西)。还有一个例子是Haskell,它使用Monads、惰性求值、尾递归优化和高阶函数来实现异常。一些现代CPU也支持异常的基本构建模块(例如专门为Azul Systems Java Compute Accelerators设计的Vega-3 CPU)。
这里是C++异常常用的实现方式:
http://www.codesourcery.com/public/cxx-abi/abi-eh.html
虽然该文档是为Itanium架构编写的,但此处描述的实现方法同样适用于其他架构。需要注意的是,由于C++异常比较复杂,因此该文档相对较长。
这里有关于LLVM如何实现异常的良好描述:
http://llvm.org/docs/ExceptionHandling.html
由于LLVM旨在成为许多运行时的通用中间表示,因此所描述的机制可以应用于许多语言。
setjmp/longjmp
提供了一个不错的在纯C中实现异常处理的方法。他提供了TRY/RAISE/EXCEPT/FINALLY宏,可以模拟几乎所有C++异常处理的功能并且更多。C/C++编译器使用底层的操作系统工具进行异常处理。像.NET或Java这样的框架也在虚拟机中依赖于操作系统工具。例如,在Windows中,真正的重活是由SEH(Structured Exception Handling)基础设施完成的。您绝对应该阅读旧的参考文章:《Win32™结构化异常处理深入浅出》。
至于不使用异常的成本,它们很昂贵,但与什么相比呢?与返回错误代码相比?在考虑正确性和代码质量的成本后,商业应用程序始终会选择异常。除了一些非常关键的操作系统级别的功能外,异常总体上都更好。
最后,还有一个反模式,即将异常用于流程控制。异常应该是异常情况,滥用异常来控制流程的代码将付出性能代价。
setjmp()
和longjmp()
通常用于IT技术中。
捕获异常确实会带来一定的成本,但对于大多数情况而言,这并不是一个大问题。
throw
和 catch
在单个内联代码块中(实际上可以跨越多个方法甚至多个类),那么它只是一个 jmp
,也就是说,它的速度与 if
/return
完全相同。 - Jörg W Mittag