rust - 使用闭包从 Option<&T> 获取原始指针是否安全?

标签 rust

我有一个Option<&T>我想要一个原始的*const T如果选项为 None 则为 null 。我想包装一个 FFI 调用,该调用采用指向 Rust 分配的对象的指针。

此外,我正在使用的 FFI 接口(interface)具有借用语义(我分配某些内容并传入指向它的指针),而不是所有权语义

extern "C" {
    // Parameter may be null
    fn ffi_call(*const T);
}

fn safe_wrapper(opt: Option<&T>) {
    let ptr: *const T = ???;
    unsafe { ffi_call(ptr) }
}

我可以使用 match声明来执行此操作,但该方法感觉非常冗长。

let ptr = match opt {
    Some(inner) => inner as *const T,
    None => null(),
};

我还可以将引用映射到指针,然后使用 unwrap_or .

let ptr = opt.map(|inner| inner as *const T).unwrap_or(null());

但是,我担心指针在通过闭包时可能会失效。 Rust 是否保证最终指针将指向与原始引用相同的东西?如果TCopy ,这是否以有意义的方式改变了语义?有没有更好的方法让我忽略?

最佳答案

是的,这是安全的。我会把它写成:

use std::ptr;

fn safe_wrapper(opt: Option<&u8>) {
    let p = opt.map_or_else(ptr::null, |x| x);
    unsafe { ffi_call(p) }
}

如果您发现自己写了很多这样的内容,您可以将其变成一个特征并将其减少为单个方法调用。

the pointer might be invalidated as it passes through the closure

如果您自己以某种方式使其无效,则可能会这样。因为该函数采用引用,所以您可以确定引用的值在函数调用期间有效 - 这就是 Rust 借用检查器的目的。

指针变得无效的唯一方法是更改​​指针的值(例如,向其添加偏移量)。既然你不这样做,那就没问题。

Does Rust make a guarantee that the final pointer will point to the same thing as the original reference?

这取决于你所说的“最终”是什么意思。将引用转换为指针将始终导致两个值包含内存中的相同位置。其他任何东西都可能是故意恶意的,而且一开始就没有人会使用 Rust。

If T is Copy, does this change the semantics in a meaningful way?

没有。此外,我们正在谈论 &T,即 始终 复制

另请参阅:


the FFI interface I am using has borrowing semantics (I allocate something and pass in a pointer to it), not ownership semantics

需要明确的是,您不能纯粹根据函数类型来确定所有权。

此 C 函数取得所有权:

void string_free(char *)

此 C 函数借用:

size_t string_len(char *)

两者都采用指针。 Rust 通过明确界定什么是借用和什么是所有权转移来改善这种情况。

extern "C" {
    // Parameter may be null
    fn ffi_call(*const T);
}

这段代码毫无意义;它没有定义泛型类型 T 并且 FFI 函数无论如何也不能具有泛型类型。

关于rust - 使用闭包从 Option<&T> 获取原始指针是否安全?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55320663/

相关文章:

Rust 通过空格分割线 : No method collect found for type &str

rust - 无法在函数指针上使用特征

performance - HashMap 和 Vec 之间的内存高效转换

rust - 如何在 future 链中使用包含在结果类型中的套接字?

rust - 了解 Rust 中参数化结构的生命周期

rust - 如何创建一个从迭代器的迭代器创建笛卡尔积迭代器的函数?

rust - 柴油。火箭和火箭.rs : don't understand why it wants a databases table

unit-testing - 在运行完所有测试之后,是否可以执行拆解功能?

module - 使用标准库中的模块可以在我的 crate root 中使用,但不能在模块中使用

Rust GTK+ 示例无法编译,因为 Option<&str> : From<Option<&String>> is not satisfied