根据文件,
Swift中的错误处理不涉及展开调用堆栈,a 过程可能是计算上昂贵的
我想知道它是什么意思?我一直认为堆栈展开是一个在异常情况下(就C ++而言)正确调用析构函数的过程。
所以我决定对情况进行建模:
class A {
init() {
print("Inited")
}
deinit {
print("Deinited")
}
}
func f() throws {
let a = A()
throw MyError.e
}
输出结果为:
Inited
Deinited
所以"析构函数"被称为 - 这意味着(在我的理解中)堆栈展开在Swift中起作用。
任何人都可以解释为什么文档说它是
没有参与
答案 0 :(得分:7)
堆栈展开只是在堆栈中导航寻找处理程序的过程。维基百科summarizes it as follows:
在此搜索过程中,某些语言要求展开堆栈。也就是说,如果函数
f
包含异常H
的处理程序E
,则调用函数g
,而函数h
又调用函数E
和异常{ {1}}中出现{1}},然后h
和h
可能会被终止,g
中的H
会处理f
。< / p>
而Swift错误不会解除堆栈查找处理程序的问题。它只是返回,并期望调用者处理抛出的错误。事实上,你引用goes on to say之后的句子:
因此,
E
语句的性能特征与throw
语句的性能特征相当。
因此,使用第一个示例,其中return
调用f
调用g
,在Swift中,如果您希望h
捕获{{1}引发的错误然后:
f
必须明确标记为h
错误; h
必须明确throws
调用g
; try
也必须标记为h
错误;和g
必须明确throws
调用f
。 简而言之,虽然其他一些语言在查找异常处理程序的过程中提供了堆栈展开,但在Swift错误处理中,您必须明确try
函数g
抛出的错误,或者是指定为catch
的函数,以便将失败的try
调用返回给调用者。在Swift中没有自动展开堆栈。
所有这些都与是否发生解除分配无关。正如您所见,是的,Swift中的throws
与try
的行为非常相似,会释放这些局部变量。
值得注意的是,并非所有涉及堆栈展开的异常处理都会进行重新分配。通常它确实如此(因为当我们处理异常时我们希望它清理),但是例如,“当发生未处理的异常时,GNU C ++ unwinder不会调用对象析构函数。原因是为了提高可调试性。 “ (来自Exception Handling in LLVM。)显然,这仅适用于调试环境中未处理的异常,但它说明了展开堆栈并不一定意味着对象被释放的问题。
答案 1 :(得分:0)
如果swift堆栈展开,那么它将调用自块开始以来分配的所有对象的所有析构函数。但反过来可能并非如此。仅仅因为为你的对象A
调用析构函数,不意味着快速堆栈展开。此外,如果你真的想测试它是否是堆栈展开,你应该尝试一个更严格的例子