当前位置 : 主页 > 手机开发 > 其它 >

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

来源:互联网 收集:自由互联 发布时间:2021-06-11
根据文件, error handling in Swift does not involve unwinding the call stack, a process that can be computationally expensive 我想知道它是什么意思?我一直认为堆栈展开是一个在异常情况下(就C而言)正确调用析
根据文件,

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开始.)显然,这仅适用于调试环境中的未处理异常,但它说明了展开堆栈并不一定意味着对象被解除分配的问题.

网友评论