rust - 为什么恐慌时恐慌会导致非法指令?
问题描述
考虑以下故意导致双重恐慌的代码:
use scopeguard::defer; // 1.1.0
fn main() {
defer!{ panic!() };
defer!{ panic!() };
}
我知道这通常发生在Drop
从先前的恐慌中展开时实现恐慌,但为什么它会导致程序发出非法指令?听起来代码已损坏或意外跳转到某个地方。我认为这可能与系统或代码生成有关,但我在各种平台上进行了测试,它们都以相同的原因发出类似的错误:
Linux:
thread panicked while panicking. aborting. Illegal instruction (core dumped)
窗户(带
cargo run
):thread panicked while panicking. aborting. error: process didn't exit successfully: `target\debug\tests.exe` (exit code: 0xc000001d, STATUS_ILLEGAL_INSTRUCTION)
锈游乐场:
thread panicked while panicking. aborting. timeout: the monitored command dumped core /playground/tools/entrypoint.sh: line 11: 8 Illegal instruction timeout --signal=KILL ${timeout} "$@"
这是怎么回事?这是什么原因造成的?
解决方案
这种行为是有意的。
来自Jonas Schievink在为什么 Drop impl 中的恐慌会导致 SIGILL 中的评论?:
它调用
intrinsics::abort()
,LLVM 变成一条ub2
指令,这是非法的,因此 SIGILL
我找不到任何有关如何处理双重恐慌的文档,但有一段std::intrinsics::abort()
与此行为一致:
在大多数平台上,当前的实现
intrinsics::abort
是调用无效指令。在 Unix 上,进程可能会以类似SIGABRT
,SIGILL
,SIGTRAP
或SIGSEGV
的信号终止SIGBUS
。精确的行为无法保证且不稳定。
奇怪的是,这种行为与 call 不同std::process::abort()
,后者总是以SIGABRT
.
x86 上选择的非法指令是UD2
(我认为上面的评论中有错字)又名未定义的指令,自相矛盾地被保留并记录为不是指令。所以没有损坏或无效跳转,只是一种快速而响亮的方式告诉操作系统出现了非常错误的问题。
推荐阅读
- node.js - 如何在服务器上的 express 和 node 中创建文件,然后将其下载到我的客户端。我正在为我的前端和后端使用 NextJS
- python - 如何创建更具活力的 Scrapy Spider?
- javascript - 在循环中声明的 React js 函数包含对“允许”变量的不安全引用
- git - 有没有办法对存储库中的各个组件进行版本/标记?
- angular - 直接从 Angular 连接到 Firebase 数据库是否安全?
- swift - 如何为 KCFloatingActionButton 定义 touchUpInside 动作?
- c - 用 fork 创建 num 个进程,然后删除一些我不会使用的进程
- python - 有一个错误需要解密一个整数
- javascript - 使用 Reactjs 的点表示法与括号表示法
- r - 查找值为零的行并在其前后添加行数