我正在实现一个C库的包装器,它接受回调,回调将在Rust中实现.鉴于在从C调用时对Rust的恐慌是未定义的行为,我想在他们进入C之前捕获任何潜在的Rust恐慌.
我一直在读书std::panic::catch_unwind.包装器对性能敏感,我宁愿避免使用类似的类型Mutex.我想把我的结果保存在一个Option<i32>并且Some(value)在没有恐慌的情况下设置它.None将表明该功能未成功执行,因此必须发生恐慌.
是Option<i32>放松安全吗?如果没有,在什么条件下会出现问题?我可以把它包起来std::panic::AssertUnwindSafe吗?
这是一个我用来AssertUnwindSafe包装整个闭包的例子.
use std::panic::{self, AssertUnwindSafe};
fn random_function_that_might_panic(a: i32) -> i32 {
if a == 42 {
panic!("did you forget a towel?");
}
a * 2
}
fn do_not_panic(a: i32) {
let mut result = None;
let unwind_state = panic::catch_unwind(AssertUnwindSafe(|| {
result = Some(random_function_that_might_panic(a)); // get result, but this could panic
}));
match unwind_state {
Ok(()) => {
match result {
Some(value) => {
println!("Result: {:?}", value);
}
None => {
// this should never happen...
println!("No result but no panic?");
}
}
}
Err(e) => {
println!("caught panic: {:?}", e);
}
}
}
fn main() {
do_not_panic(1);
do_not_panic(2);
do_not_panic(3);
do_not_panic(42);
}
Run Code Online (Sandbox Code Playgroud)
(在操场上看到上面的内容.)
我无法弄清楚如何只是包装Option<i32>的AssertUnwindSafe,所以在这里我包裹了整个封闭.我怎么包装Option<i32>?
是
Option<i32>放松安全吗?
是.当你可以询问编译器时,没有理由向人类询问这个问题:
fn implements<T: std::panic::UnwindSafe>() {}
fn main() {
implements::<Option<i32>>();
}
Run Code Online (Sandbox Code Playgroud)
你真正的问题应该是:
是
&mut Option<i32>放松安全吗?
这不是,但你可能已经知道了.我猜你在添加之前得到了这个编译器错误AssertUnwindSafe,告诉你它不安全:
error[E0277]: the trait bound `&mut std::option::Option<i32>: std::panic::UnwindSafe` is not satisfied in `[closure@src/main.rs:12:44: 14:6 result:&mut std::option::Option<i32>, a:&i32]`
--> src/main.rs:12:24
|
12 | let unwind_state = panic::catch_unwind(|| {
| ^^^^^^^^^^^^^^^^^^^ the type &mut std::option::Option<i32> may not be safely transferred across an unwind boundary
|
= help: within `[closure@src/main.rs:12:44: 14:6 result:&mut std::option::Option<i32>, a:&i32]`, the trait `std::panic::UnwindSafe` is not implemented for `&mut std::option::Option<i32>`
= note: required because it appears within the type `[closure@src/main.rs:12:44: 14:6 result:&mut std::option::Option<i32>, a:&i32]`
= note: required by `std::panic::catch_unwind`
Run Code Online (Sandbox Code Playgroud)
我会把你的代码写成这样,因为它值得:
fn do_not_panic(a: i32) {
let result = panic::catch_unwind(|| random_function_that_might_panic(a)).ok();
match result {
Some(value) => {
println!("Result: {:?}", value);
}
None => {
println!("caught panic");
}
}
}
Run Code Online (Sandbox Code Playgroud)
没有可变变量,没有额外的嵌套,没有"这应该永远不会发生"的评论.
也可以看看:
| 归档时间: |
|
| 查看次数: |
534 次 |
| 最近记录: |