微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Swift中的错误处理不涉及堆栈展开.这是什么意思?

根据文件,

error handling in Swift does not involve unwinding the call stack,a
process that can be computationally expensive

我想知道它是什么意思?我一直认为堆栈展开是一个在异常情况下(就C而言)正确调用析构函数的过程.

所以我决定对情况进行建模:

class A {
    init() {
        print("Inited")
    }
    deinit {
        print("Deinited")
    }
}

func f() throws {
    let a = A()
    throw MyError.e
}

输出是:

Inited
Deinited

所以“析构函数”被调用 – 这意味着(在我的理解中)堆栈展开在Swift中起作用.

任何人都可以解释为什么文档说它是

not involved

解决方法

堆栈展开只是导航堆栈中寻找处理程序的过程.维基百科 summarizes it as follows

Some languages call for unwinding the stack as this search progresses. That is,if function f,containing a handler H for exception E,calls function g,which in turn calls function h,and an exception E occurs in h,then functions h and g may be terminated,and H in f will handle E.

而Swift错误不会解除堆栈查找处理程序的问题.它只是返回,并期望调用者处理抛出的错误.事实上,你引用goes on to say之后的句子:

As such,the performance characteristics of a throw statement are comparable to those of a return statement.

所以,使用第一个例子,其中f调用g来调用h,在Swift中,如果你想要f来捕获由h抛出的错误,那么:

> h必须明确标记为抛出错误;
> g必须明确地尝试调用h;
> g也必须标记它也会引发错误;和
> f必须明确地尝试调用g.

简而言之,虽然其他一些语言在查找异常处理程序的过程中提供堆栈展开,但在Swift错误处理中,您必须显式捕获您尝试的函数抛出的错误,或者将其指定为抛出的函数,以便尝试调用失败将被抛回调用者.在Swift中没有自动展开堆栈.

所有这些都与是否发生解除分配无关.正如您所见,是的,Swift中的抛出与返回非常相似,可以释放那些局部变量.

值得注意的是,并非所有涉及堆栈展开的异常处理都会进行重新分配.通常它确实如此(因为当我们处理异常时我们希望它清理),但是例如,“当发生未处理的异常时,GNU C unwinder不会调用对象析构函数.原因是为了提高可调试性. “ (从Exception Handling in LLVM开始.)显然,这仅适用于调试环境中的未处理异常,但它说明了展开堆栈并不一定意味着对象被解除分配的问题.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐