如何修复 VaList 的 "may not be safely transferred across an unwind boundary"?
How do I fix "may not be safely transferred across an unwind boundary" for VaList?
我正在尝试 override/wrap 使用 Rust 代码的 Libc vprintf(format, va_list)
函数。为此,我需要将 VaList
参数传递给还需要捕获展开错误的不安全代码:
#![feature(c_variadic)]
extern crate libc;
use libc::{c_char, c_int};
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
if true {
::std::panic::catch_unwind(|| hook_fn(format, args)).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, args))
}
pub unsafe fn hook_fn(format: *const c_char, args: std::ffi::VaList) -> c_int {
0
}
fn main() {
println!("Hello, world!");
}
我的代码无法编译:
error[E0277]: the type `&mut std::ffi::VaListImpl<'_>` may not be safely transferred across an unwind boundary
--> src/main.rs:8:9
|
8 | ::std::panic::catch_unwind(|| hook_fn(format, args)).ok()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------------ within this `[closure@src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`
| |
| `&mut std::ffi::VaListImpl<'_>` may not be safely transferred across an unwind boundary
|
= help: within `[closure@src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`, the trait `std::panic::UnwindSafe` is not implemented for `&mut std::ffi::VaListImpl<'_>`
= note: `std::panic::UnwindSafe` is implemented for `&std::ffi::VaListImpl<'_>`, but not for `&mut std::ffi::VaListImpl<'_>`
= note: required because it appears within the type `std::ffi::VaList<'_, '_>`
= note: required because it appears within the type `[closure@src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`
某些类型,尤其是 FFI 类型,如果在恐慌后使用,可能会导致未定义的行为。这种安全性通过类型是否实现 UnwindSafe
来跟踪,而 VaList
不实现。
这在错误消息的第一“帮助”行中有解释:
= help: within `[closure@src/main.rs:8:36: 8:61 format:&*const i8, args:std::ffi::VaList<'_, '_>]`,
the trait `std::panic::UnwindSafe` is not implemented for `&mut std::ffi::VaListImpl<'_>`
第一个“注意”也给了你一个可能的解决方案:
note: `std::panic::UnwindSafe` is implemented for `&std::ffi::VaListImpl<'_>`, but not for `&mut std::ffi::VaListImpl<'_>`
它告诉您 可以安全地跨展开边界共享对 VaListImpl
的不可变引用。因此,您可以通过引用传递值来修复您的代码:
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
if true {
::std::panic::catch_unwind(|| hook_fn(format, &args)).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, &args))
}
pub unsafe fn hook_fn(format: *const c_char, args: &std::ffi::VaList) -> c_int {
0
}
这有助于解决问题。
不确定这是否是解决此问题的正确方法。 Peter Halls 上面的建议可能仍然是正确的。但它似乎并没有为我修复错误。
#![feature(c_variadic)]
extern crate libc;
use libc::{c_char, c_int};
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
let ap : VaListImpl = args.clone();
if true {
::std::panic::catch_unwind(|| hook_fn(format, ap.clone())).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, args))
}
pub unsafe fn hook_fn(format: *const c_char, args: std::ffi::VaList) -> c_int {
0
}
fn main() {
println!("Hello, world!");
}
我正在尝试 override/wrap 使用 Rust 代码的 Libc vprintf(format, va_list)
函数。为此,我需要将 VaList
参数传递给还需要捕获展开错误的不安全代码:
#![feature(c_variadic)]
extern crate libc;
use libc::{c_char, c_int};
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
if true {
::std::panic::catch_unwind(|| hook_fn(format, args)).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, args))
}
pub unsafe fn hook_fn(format: *const c_char, args: std::ffi::VaList) -> c_int {
0
}
fn main() {
println!("Hello, world!");
}
我的代码无法编译:
error[E0277]: the type `&mut std::ffi::VaListImpl<'_>` may not be safely transferred across an unwind boundary
--> src/main.rs:8:9
|
8 | ::std::panic::catch_unwind(|| hook_fn(format, args)).ok()
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ ------------------------ within this `[closure@src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`
| |
| `&mut std::ffi::VaListImpl<'_>` may not be safely transferred across an unwind boundary
|
= help: within `[closure@src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`, the trait `std::panic::UnwindSafe` is not implemented for `&mut std::ffi::VaListImpl<'_>`
= note: `std::panic::UnwindSafe` is implemented for `&std::ffi::VaListImpl<'_>`, but not for `&mut std::ffi::VaListImpl<'_>`
= note: required because it appears within the type `std::ffi::VaList<'_, '_>`
= note: required because it appears within the type `[closure@src/main.rs:8:36: 8:60 format:&*const i8, args:std::ffi::VaList<'_, '_>]`
某些类型,尤其是 FFI 类型,如果在恐慌后使用,可能会导致未定义的行为。这种安全性通过类型是否实现 UnwindSafe
来跟踪,而 VaList
不实现。
这在错误消息的第一“帮助”行中有解释:
= help: within `[closure@src/main.rs:8:36: 8:61 format:&*const i8, args:std::ffi::VaList<'_, '_>]`,
the trait `std::panic::UnwindSafe` is not implemented for `&mut std::ffi::VaListImpl<'_>`
第一个“注意”也给了你一个可能的解决方案:
note: `std::panic::UnwindSafe` is implemented for `&std::ffi::VaListImpl<'_>`, but not for `&mut std::ffi::VaListImpl<'_>`
它告诉您 可以安全地跨展开边界共享对 VaListImpl
的不可变引用。因此,您可以通过引用传递值来修复您的代码:
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
if true {
::std::panic::catch_unwind(|| hook_fn(format, &args)).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, &args))
}
pub unsafe fn hook_fn(format: *const c_char, args: &std::ffi::VaList) -> c_int {
0
}
这有助于解决问题。 不确定这是否是解决此问题的正确方法。 Peter Halls 上面的建议可能仍然是正确的。但它似乎并没有为我修复错误。
#![feature(c_variadic)]
extern crate libc;
use libc::{c_char, c_int};
pub unsafe extern "C" fn vprintf(format: *const c_char, args: std::ffi::VaList) -> c_int {
let ap : VaListImpl = args.clone();
if true {
::std::panic::catch_unwind(|| hook_fn(format, ap.clone())).ok()
} else {
None
}
.unwrap_or_else(|| hook_fn(format, args))
}
pub unsafe fn hook_fn(format: *const c_char, args: std::ffi::VaList) -> c_int {
0
}
fn main() {
println!("Hello, world!");
}