Rust FFI 边界未定义行为何时会发生恐慌?

问题描述 投票:0回答:1

rustnomicon 包含以下示例:

#[no_mangle]
extern "C" fn assert_nonzero(input: u32) {
    assert!(input != 0)
}

如果使用参数

assert_nonzero
调用
0
,则运行时保证(安全)中止该进程,无论是否使用
panic=abort
进行编译。


另一方面,Rust Reference 声称:

行为被视为未定义:[...]使用错误的调用 ABI 调用函数或从具有错误的展开 ABI 的函数展开。


这两种说法对我来说似乎是矛盾的。

assert_nonzero
具有
C
ABI,但可以从 Rust 恐慌中解脱出来。那么这是保证(安全)中止,还是UB?不可能两者兼而有之。

Chayim Friedman 在另一个问题中善意地建议这确实是 UB。

Rustnomicon 是否已经过时了,还是我误解了什么?

更一般地说:跨越 FFI 边界的 Rust 恐慌何时被视为未定义行为?

rust language-lawyer undefined-behavior ffi
1个回答
1
投票

来自

-unwind
ABI 的 RFC:

现有 ABI 字符串行为的更改

在此 RFC 之前,任何跨越

extern "C"
边界的展开操作,无论是来自 Rust 函数的
panic!
“转义” 使用
extern "C"
定义或通过从另一种语言输入 Rust 来定义 通过使用
extern "C"
声明的入口点,导致未定义 行为。

此 RFC 保留了大部分未定义的行为,但有一个例外: 对于

panic=unwind
运行时,
panic!
将导致
abort
如果 否则会从用
extern "C"
.

定义的函数中“逃逸”

此更改将应用于除

"Rust"
之外的所有 ABI 字符串, 比如
"system"

所以看起来这曾经是UB,但是在这个RFC被接受之后,这不再是UB并且肯定会中止。

我不知道我们是否可以说该引用已过时,因为我们可以说我们只是不会因

extern "C"
Rust 函数的恐慌而放松(而是中止)。

© www.soinside.com 2019 - 2024. All rights reserved.