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合同。
}