Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/jpa/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Memory Box::pin()与pin::new_unchecked()_Memory_Rust_Stack_Heap Memory_Drop - Fatal编程技术网

Memory Box::pin()与pin::new_unchecked()

Memory Box::pin()与pin::new_unchecked(),memory,rust,stack,heap-memory,drop,Memory,Rust,Stack,Heap Memory,Drop,试图理解Box::pin()和pin::new\u unchecked()之间的区别。假设以下代码: use std::pin::Pin; use std::marker::PhantomPinned; struct Foo { x: i32, _pin: PhantomPinned, } fn bar() { let fives = Foo { x: 5, _pin: PhantomPinned, }; let mu

试图理解
Box::pin()
pin::new\u unchecked()
之间的区别。假设以下代码:

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();
}
使用std::pin::pin;
使用std::marker::phantompinted;
结构Foo{
x:i32,
_别针:幽灵别针,
}
fn bar(){
让五=福{
x:5,
_别针:幽灵别针,
};
让mut boxed=Box::pin(五个);
不安全{
让mut_ref:Pin=Pin::as_mut(&mut已装箱);
Pin::get_unchecked_mut(mut_ref).x=55;
}
println!(“五个:{}”,boxed.x);
//fives.x=555;//不会编译Box::pin()消耗的fives。
让mut twos=Foo{
x:2,
_别针:幽灵别针,
};
让mut ptr=unsafe{Pin::new_unchecked(&mut twos)};
不安全{
让mut_ref:Pin=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();
}
我的理解是:

  • 所有者是
    装箱的
    两个
    ,因此当他们超出范围时将调用
    drop()
  • Foo
    无需手动实现
    drop()
  • 堆上存在五个,堆栈上存在两个

这是正确的吗?何时
Box::pin()
合适,何时
pin::new\u unchecked()
合适?对于
,什么时候需要实现
drop()!取消pin
struct?

Box::pin始终可以安全使用。已装箱的值已归长方体所有,将其移动到
Pin
可确保此时没有其他引用,因为借用检查器不允许移动。只有实现了由类型检查器强制执行的
Unpin
,才能取消固定内容

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

碰巧,
Pin::new_unchecked
始终可以安全地与不可变的
&
-引用和
框一起使用。但是,与可变
&mut
-引用
Rc
或原始指针一起使用是不安全的,除非您单独确保强制执行所有引脚保证。中有有关
Pin::new_unchecked
安全性的详细信息

本文档提供了
Pin::new_unchecked
如何导致带有
&mut
参考的UB的示例:

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.
}
使用std::mem;
使用std::pin::pin;
fn移动固定参考(多个a:T,多个b:T){
不安全{
设p:Pin=Pin::new_未选中(&mut a);
//这意味着指针“a”永远不能再移动了。
}
mem::swap(&mut a和&mut b);
//'a'的地址更改为'b'的堆栈插槽,因此'a'被移动了
//虽然我们之前已经锁定了它!但我们违反了锁定API合同。
}