首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >方框:pin() vs Pin::new_unchecked()

方框:pin() vs Pin::new_unchecked()
EN

Stack Overflow用户
提问于 2020-11-27 20:54:28
回答 1查看 701关注 0票数 1

试图理解Box::pin()Pin::new_unchecked()之间的区别。假设以下代码:

代码语言:javascript
复制
use std::pin::Pin;
use std::marker::PhantomPinned;

struct Foo {
    x: i32,
    _pin: PhantomPinned,
}

fn bar() {

    let fives = Foo {
        x: 5,
        _pin: PhantomPinned,
    };
    let mut boxed = Box::pin(fives);
    unsafe {
        let mut_ref: Pin<&mut Foo> = Pin::as_mut(&mut boxed);
        Pin::get_unchecked_mut(mut_ref).x = 55;
    }
    println!("fives: {}", boxed.x);
    // fives.x = 555; //Won't compile Box::pin() consumed fives.
    
    let mut twos = Foo {
        x: 2,
        _pin: PhantomPinned,
    };
    let mut ptr = unsafe{ Pin::new_unchecked(&mut twos) };
    unsafe {
        let mut_ref: Pin<&mut Foo> = Pin::as_mut(&mut ptr);
        Pin::get_unchecked_mut(mut_ref).x = 22;
    }
    println!("twos: {}", twos.x);
    twos.x = 222;
    println!("twos: {}", twos.x);
}

fn main() {
    bar();
}

我的理解是:

  • 所有者是boxedtwos,因此当它们超出范围时,会调用drop()
  • drop()不需要为Foo手动实现。
  • fives存在于堆中,twos存在于堆栈中。

这是正确的吗?什么时候Box::pin()合适,什么时候Pin::new_unchecked()合适?什么时候需要为一个drop()结构实现!Unpin

EN

回答 1

Stack Overflow用户

发布于 2020-11-27 22:32:22

Box::pin始终是安全的使用。盒式值已经属于该框,并将其移动到一个Pin中,以保证当时没有其他对其的引用,因为借入检查器不会允许移动发生。只有在实现由类型检查器强制执行的Unpin时,内容才能解除锁定。

Pin::new_unchecked并不总是安全的使用。它采用任意指针类型,而不仅仅是一个框,并且可能存在该指针的其他副本。因为指针可以是任何东西,所以编译器不能保证它所指向的数据不会被其他代码移动,除非先解除锁定。当您使用Pin::new_unchecked时,这取决于您是否强制执行生成Pin的用户所期望的所有假设。如果不这样做,则可能触发未定义的行为。

碰巧,Pin::new_unchecked总是可以安全地与不可变的&-references和Box一起使用。但是,与可变的&mut-references RcArc或原始指针一起使用是不安全的,除非您独立地确保所有的引脚保证都被强制执行。详细介绍了Pin::new_unchecked其文件中的安全性。

文档提供了Pin::new_unchecked如何使用&mut引用导致UB的示例:

代码语言:javascript
复制
use std::mem;
use std::pin::Pin;

fn move_pinned_ref<T>(mut a: T, mut b: T) {
    unsafe {
        let p: Pin<&mut T> = Pin::new_unchecked(&mut a);
        // This should mean the pointee `a` can never move again.
    }
    mem::swap(&mut a, &mut b);
    // The address of `a` changed to `b`'s stack slot, so `a` got moved even
    // though we have previously pinned it! We have violated the pinning API contract.
}
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65043756

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档