首页 > 解决方案 > 为什么恐慌时恐慌会导致非法指令?

问题描述

考虑以下故意导致双重恐慌的代码:

use scopeguard::defer; // 1.1.0

fn main() {
    defer!{ panic!() };
    defer!{ panic!() };
}

我知道这通常发生在Drop从先前的恐慌中展开时实现恐慌,但为什么它会导致程序发出非法指令?听起来代码已损坏或意外跳转到某个地方。我认为这可能与系统或代码生成有关,但我在各种平台上进行了测试,它们都以相同的原因发出类似的错误:

这是怎么回事?这是什么原因造成的?

标签: rustpanicillegal-instruction

解决方案


这种行为是有意的。

来自Jonas Schievink为什么 Drop impl 中的恐慌会导致 SIGILL 中的评论?

它调用intrinsics::abort(),LLVM 变成一条ub2指令,这是非法的,因此 SIGILL

我找不到任何有关如何处理双重恐慌的文档,但有一段std::intrinsics::abort()与此行为一致:

在大多数平台上,当前的实现intrinsics::abort是调用无效指令。在 Unix 上,进程可能会以类似SIGABRT, SIGILL,SIGTRAPSIGSEGV的信号终止SIGBUS。精确的行为无法保证且不稳定。

奇怪的是,这种行为与 call 不同std::process::abort(),后者总是以SIGABRT.

x86 上选择的非法指令是UD2(我认为上面的评论中有错字)又名未定义的指令,自相矛盾地被保留并记录为不是指令。所以没有损坏或无效跳转,只是一种快速而响亮的方式告诉操作系统出现了非常错误的问题。


推荐阅读