Nic*_*ick 4 error-handling exception-handling swift
根据文件,
Swift中的错误处理不涉及展开调用堆栈,这个过程计算成本很高
我想知道它是什么意思?我一直认为堆栈展开是一个在异常情况下(就C++而言)正确调用析构函数的过程.
所以我决定对情况进行建模:
class A {
init() {
print("Inited")
}
deinit {
print("Deinited")
}
}
func f() throws {
let a = A()
throw MyError.e
}
Run Code Online (Sandbox Code Playgroud)
输出是:
Inited
Deinited
Run Code Online (Sandbox Code Playgroud)
所以"析构函数"被调用 - 这意味着(在我的理解中)堆栈展开在Swift中起作用.
任何人都可以解释为什么文档说它是
没有参与
?
堆栈展开只是导航堆栈中寻找处理程序的过程.维基百科总结如下:
随着搜索的进行,某些语言要求展开堆栈.也就是说,如果函数
f包含的处理程序H异常E,调用函数g,后者又调用功能h,和一个异常E发生在h,则功能h和g可以被终止,并且H在f将处理E.
而Swift错误不会解除堆栈查找处理程序的问题.它只是返回,并期望调用者处理抛出的错误.事实上,你引用的句子之后的句子继续说:
因此,
throw声明的性能特征与声明的性能特征相当return.
所以,使用第一个例子,在Swift f调用g哪个调用h,如果你想f捕获所引发的错误h,那么:
h必须明确标明它的throws错误;g必须明确地try呼吁h;g还必须标记它也是throws错误的; 和f必须明确地try调用它g.简而言之,虽然其他一些语言在查找异常处理程序的过程中提供堆栈展开,但在Swift错误处理中,您必须显式地显示catch您的函数抛出的错误try,或者将其指定为函数,throws以便将失败的try调用返回由呼叫者决定.在Swift中没有自动展开堆栈.
所有这些都与是否发生解除分配无关.正如你所见,是的,throw在Swift中表现得很像return,释放那些局部变量.
值得注意的是,并非所有涉及堆栈展开的异常处理都会进行重新分配.通常它确实如此(因为当我们处理异常时我们希望它清理),但是例如,"当发生未处理的异常时,GNU C++ unwinder不会调用对象析构函数.原因是为了提高可调试性. " (来自LLVM中的异常处理.)显然,这仅适用于调试环境中的未处理异常,但它说明了展开堆栈并不一定意味着对象被解除分配的问题.
| 归档时间: |
|
| 查看次数: |
406 次 |
| 最近记录: |