rust-course/advance/async/pin-unpin #788
Replies: 46 comments 45 replies
|
好难,始终对pin理解的不太好 |
|
图上的内存地址分别代表什么的地址,红色箭头的指向代表什么意思希望能标注或者注释下,看不太懂。因为我原先理解“移到”的意思是一个不能浅拷贝的变量值从绑定a变量换到绑定b变量,变量值内存地址是不变的,变的是b有个指向变量值的地址而且拥有所有权。而在这里貌似变量值的地址也变了,这样的话会涉及到重新分配堆内存,效率肯定低的,应该不会这么设计,所以想借助上面的图来理解值移到到底是移到的啥 |
|
看了大量的文章好像都没有说清楚一个问题(或者说没有让我看明白):到底 pin 是 1)将 move 之后的 invalid 指针重新变成了 valid,还是 2)仅仅是阻止代码构建? 将值固定到栈上 的例子让我感觉实现的是 2),固定到堆上 的例子则有些莫名其妙,打印一下就完事了,不应该和 将值固定到栈上 的例子要对应以来吗,不 swap 一下啥的吗? 谢谢~~ |
|
所以说 |
|
我真看不懂,看了两遍 新手 |
|
这里彻底晕了 |
|
rust中Future是通过Generator实现的,看了下Generator生成的时候用了std::mem::replace来查看状态,但是参数命名是Pin的,为什么能调用std::mem::replace |
|
真的晕了。。。rust的各种指针好难记 |
|
晕了 |
|
但是实际运行后,却产生了下面的输出 |
|
这个地方写错了 但是实际运行后,却产生了下面的输出: a: test1, b: test1
a: test1, b: test2应改为 a: test2, b: test1
a: test1, b: test2应该将第一个 a: |
|
看了一下Pin的官方说明, 其实 Pin 这个结构体并不是让 Pin 中的值变的不可移动, 而是让你无法在不使用 unsafe 方法的前提下改动 Pin 中的值地址而已. 真正标志一个值是不是不可移动的只有 !Unpin 这个标志. 这就是为什么 Pin 只是一个结构体, 而 Unpin 是一个编译器自动实现的 trait 的原因. |
|
被pin住的堆上数据就不会发生移动了吗 |
|
已经麻了,这节。 |
输出 本身不难理解,互换后的俩value都打出来就好理解为什么要pin了,swap之后a的值互换,b指向的目标互换; |
|
这个Pin,Box,Arc起名真的是一眼明了。实在不行就叫i j k多好 |
|
是我漏看了吗,好像一直看到现在也没有讲到虚类型? |
Test { data: "数据", rData: 0x25ed4ff510 }
|
|
emo了 |
|
看了评论区大佬的留言,有一些看法,望指正: |
pub fn main() {
// 此时的`test1`可以被安全的移动
let mut test1 = Test::new("test1");
// 新的`test1`由于使用了`Pin`,因此无法再被移动,这里的声明会将之前的`test1`遮蔽掉(shadow)
let mut test1 = unsafe { Pin::new_unchecked(&mut test1) };
Test::init(test1.as_mut());
let mut test2 = Test::new("test2");
let mut test2 = unsafe { Pin::new_unchecked(&mut test2) };
Test::init(test2.as_mut());
println!("a: {}, b: {}", Test::a(test1.as_ref()), Test::b(test1.as_ref()));
// ??? 如果需要修改 test1.a 呢? 必须通过 test1.as_mut().get_unchecked_mut() 来获得 &mut 借用
// 那如果能够通过 test1.as_mut().get_unchecked_mut() 获得 &mut 借用, swap 也无法防止移动
std::mem::swap(test1.get_mut(), test2.get_mut());
println!("a: {}, b: {}", Test::a(test2.as_ref()), Test::b(test2.as_ref()));
}我的疑问写在这段代码里面:Pin 是通过阻止或得 &mut 借用来防止 swap 的,可是正常的变更操作(Future对象执行期间肯定会发生状态变更),还是需要通过 unsafe的方式来获取 &mut 借用。没有感觉到Pin起到了什么作用? |
|
深入理解Pin的例子中,运行结果不是 我实际运行后是 |
|
啊啊啊啊啊 |
|
Pin的“定住”的基础就是 pub fn get_mut(self) -> &'a mut T
where
T: Unpin
pub unsafe fn get_unchecked_mut(self) -> &'a mut T观察签名, |
|
感觉看不太懂,我的理解 |
|
我的理解是 Pin最根本的目的是阻止获得未实现
本质上 Pin 是一个智能指针,它实现了 impl<Ptr: DerefMut<Target: Unpin>> DerefMut for Pin<Ptr> {
fn deref_mut(&mut self) -> &mut Ptr::Target {
Pin::get_mut(Pin::as_mut(self))
}
}对于
pub const fn get_mut(self) -> &'a mut T
where
T: Unpin,
{
self.__pointer
}如果是 |
|
不能理解,为什么变量在内存中会被移动? 想不通,不管是转移所有权还是什么,内存地址不应该变化才对。以c++指针为例,只要申请了一块堆内存,只要不释放,那在整个程序运行期间都是可以访问的。 2.如果移动会导致引用失效,那我们前面所使用的引用为什么从来没考虑过这个点呢? |
|
use std::mem; #[derive(Debug)] fn main() { } 拿play.rust-lang.org跑一下就清楚了 t2: ========== 交换后 ========== t2: ========== 验证 ========== 栈地址指向"槽位":槽位 &t1.a 固定不动,但 swap 换的是槽里的内容。指针还指着老地方,内容却已易主 → 错位。 |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
advance/async/pin-unpin
https://course.rs/advance/async/pin-unpin.html
All reactions