展开(Unwinding)

    Rust有一个分层的错误处理体系:

    从1.0开始,Rust对Panic的处理显得有些混乱。在很早很早以前,Rust的设计非常接近Erlang。和Erlang一样,Rust由许多轻量级的任务(task)组成,当任务进入错误状态的时候,它们使用Panic停止自己。Panic和Java或者C++中的异常不同,它不能在任意时间点被捕获。Panic只能被任务的所有者捕获,而捕获后必须立即对它进行相应处理,否则任务会自己停止。

    而在后来Rust的发展过程中,我们推崇尽可能少的抽象,所以上文的编程风格也就显得过时了。轻量级的任务被重量级的操作系统线程所取代。不过在1.0的稳定版本中,panic还是只能被父线程捕获。这意味着捕获一个panic需要唤醒一个系统线程!这和Rust的零开销抽象的设计哲学是完全相悖的。

    Rust的展开方式没有试图和其他任何一种语言的展开方式相兼容。所以,从其他语言展开Rust的栈,或者从Rust展开其他语言的栈,全都属于未定义行为。你必须在进入FFI调用之前捕获所有的Panic!你可以决定具体的实现方法,但不能什么都不做。否则的话,最好的情况是你的应用程序会崩溃。而最坏的情况是,你的程序不会崩溃,但会在彻底混乱的状态下持续运行。