加载中...

| 中文名 | 栈展开 |
| 外文名 | Stack Unwinding |
| 触发时机 | 异常抛出 |
| 配合惯用法 | RAII |
| 相关语言 | C++、Rust |
栈展开是指在异常被抛出后,程序沿调用栈自内向外逐层回退,在离开每个函数栈帧时正确释放其局部资源,直至到达能够捕获该异常的处理块的过程,是 C++、Rust 等语言实现异常安全的关键机制。
当函数深层嵌套调用中发生异常,控制流不能像正常返回那样逐层 return,而是需要跳过中间函数直接寻找处理器。但中间函数栈帧中已构造的局部对象必须被妥善清理,否则会造成资源泄漏。栈展开就是负责这一有序清理的过程,它保证即使跨越多层调用,已分配的内存、文件句柄、锁等资源仍能通过析构函数正确释放。
现代编译器通常采用零开销异常模型,在无异常发生时不产生额外运行时代价,而是借助编译期生成的展开表在异常发生时按元数据驱动清理。C++ 的 RAII 惯用法与栈展开紧密配合:资源在构造时获取、在析构时释放,栈展开自动触发析构,从而实现异常安全。
问:析构函数抛出异常为什么危险?答:若栈展开过程中某个析构函数又抛出新异常,运行时同时面对两个异常无法处理,会直接调用 terminate 终止程序,因此析构函数应当保证不抛异常。
问:栈展开和 setjmp/longjmp 有何区别?答:longjmp 直接跳转,不会调用中间栈帧的析构函数,可能泄漏资源;而栈展开会有序析构每层局部对象,是类型安全且资源安全的。

| 中文名 | 栈展开 |
| 外文名 | Stack Unwinding |
| 触发时机 | 异常抛出 |
| 配合惯用法 | RAII |
| 相关语言 | C++、Rust |
登录 后参与讨论
暂无讨论,来发表第一条评论吧