#shared-ptr #pointers #alias #safely #drop #raw-pointers #reference

alias-ptr

(主要) Rust 中的手动释放的(大部分)安全共享指针

1 个不稳定版本

0.1.0 2021 年 6 月 29 日

#2654Rust 模式

MIT/Apache

12KB
72

AliasPtr – (大部分) Rust 中的安全共享指针

alias-ptr 库提供了 AliasPtr 类型,允许安全地创建指向同一堆内存分配的多个指针,并且(不安全地)释放内存而不产生引用计数开销。

AliasPtr 类型是一个指针,其 API 设计模仿 RcArc(提供对目标的共享 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-refVecRef类型并不不安全,因为当前保证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”子目录。

无运行时依赖