Я реализую оболочку библиотеки C, которая принимает обратные вызовы, и обратные вызовы будут реализованы в Rust. Учитывая, что паника в Rust при вызове из C является неопределенным поведением , я хочу уловить любую потенциальную панику в Rust до того, как она попадет в C.
Я читал о 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);
}
(см. Выше на детской площадке .)
Я не мог понять, как обернуть просто Option<i32>
в AssertUnwindSafe
, поэтому здесь я завернул всю затвор. Как бы мне обернуть только Option<i32>
?