1 个不稳定版本
0.1.0 | 2021 年 6 月 29 日 |
---|
#2654 在 Rust 模式
12KB
72 行
AliasPtr – (大部分) Rust 中的安全共享指针
alias-ptr
库提供了 AliasPtr
类型,允许安全地创建指向同一堆内存分配的多个指针,并且(不安全地)释放内存而不产生引用计数开销。
AliasPtr
类型是一个指针,其 API 设计模仿 Rc
或 Arc
(提供对目标的共享 Deref
访问)。与它们不同,AliasPtr
预期用户手动删除目标(一个 unsafe
操作)。这是为了像 C++ 中的原始指针一样工作,它允许对底层数据的别名访问,以及手动释放/删除内存。
这不是为了取代 Rust 的安全抽象(如 Box)的使用,而是作为必要且无法轻易规避的多个所有权的后备方案,但又不希望有 Rc 或 Arc 的开销。预期用途是在数据结构中使用 AliasPtr
,就像使用 Rc
一样,仔细审查不安全的 Drop
逻辑,以确保您不会使用-after-free,并向用户公开一个安全的 API。
例如,可以使用AliasPtr
来构建一个与owning_ref::BoxRef
使用Box
别名*const
(在Stacked Borrows下不安全,在Miri测试中失败,并且一旦rustc为可变指针启用noalias,可能会产生错误的编译)的合理替代品。然而,由于BoxRef
仅仅是owning_ref::OwningRef
的一个类型别名,它是泛型化拥有类型的(引用始终是*const
),将BoxRef<T>
更改为使用AliasPtr<T>
而不是Box<T>
,这将破坏期望BoxRef<T>
与OwningRef<Box<T>, T>
相同类型的库用户。
有趣的是,owning-ref
的VecRef
类型并不不安全,因为当前保证Vec
在移动时不会使对其元素的引用失效(Vec
将不会使用noalias
)。参见"《Vec<T>
和其他标准容器的别名规则"}。
安装
alias-ptr
计划在https://crates.org.cn/alias-ptr发布。
文档将位于https://docs.rs/alias-ptr。
用法
use alias_ptr::AliasPtr;
use std::cell::Cell;
struct AliasedPair(AliasPtr<Cell<i32>>, AliasPtr<Cell<i32>>);
impl AliasedPair {
fn new(x: i32) -> AliasedPair {
let x = AliasPtr::new(Cell::new(x));
AliasedPair(x.copy(), x)
}
}
impl Drop for AliasedPair {
fn drop(&mut self) {
unsafe {
self.0.delete();
}
}
}
#[test]
fn test_aliased_pair() {
let pair = AliasedPair::new(1);
pair.0.set(42);
assert_eq!(pair.1.get(), 42);
}
设计
AliasPtr持有原始指针而不是引用(因为Miri禁止将引用传递给Box::from_raw()
),并且在每次解引用时借出共享引用。
测试
AliasPtr被设计成在Stacked Borrows下安全,启用Stacked Borrows后通过Miri测试,并且一旦rustc为可变指针启用noalias,不会产生错误的编译。
要验证它是否通过Miri测试,请运行
cargo +nightly miri test --target-dir miri
注意这会覆盖“miri”子目录。