在我编写了一些代码并阅读了一些文章后,我对Rust中的移动语义感到有些困惑。我认为值被移动后应该被释放,内存也应该失效。因此,我尝试编写一些代码来进行测试。
第一个示例
#[derive(Debug)]
struct Hello {
field: u64,
field_ptr: *const u64,
}
impl Hello {
fn new() -> Self {
let h = Hello {
field: 100,
field_ptr: std::ptr::null(),
};
h
}
fn init(&mut self) {
self.field_ptr = &self.field as *const u64;
}
}
fn main(){
let mut h = Hello::new();
h.init();
println!("=================");
println!("addr of h: ({:?}) \naddr of field ({:?})\nfield_ptr: ({:?}) \nptr value {:?}", &h as *const Hello, &h.field as *const u64, h.field_ptr, unsafe {*h.field_ptr});
let c = &h.field as *const u64;
let e = &h as *const Hello;
let a = h;
let d = &a.field as *const u64;
println!("=================");
println!("addr of a: ({:?}) \naddr of field ({:?})\nfield_ptr: ({:?}) \nptr value {:?}", &a as *const Hello, &a.field as *const u64, a.field_ptr, unsafe {*a.field_ptr});
println!("=================");
println!("addr of c {:?}\nvalue {:?}", c, unsafe {*c});
println!("addr of d {:?}\nvalue {:?}", d, unsafe {*d});
println!("addr of e {:?}\nvalue {:?}", e, unsafe {&*e});
}
以上代码的结果是:
=================
addr of h: (0x7ffee9700628)
addr of field (0x7ffee9700628)
field_ptr: (0x7ffee9700628)
ptr value 100
=================
addr of a: (0x7ffee9700720)
addr of field (0x7ffee9700720)
field_ptr: (0x7ffee9700628)
ptr value 100
=================
addr of c 0x7ffee9700628
value 100
addr of d 0x7ffee9700720
value 100
addr of e 0x7ffee9700628
value Hello { field: 100, field_ptr: 0x7ffee9700628 }
所以,我创建了一个自引用结构体Hello
并将field_ptr指向u64字段,并使用裸指针保存结构体和字段的地址,然后我将h移动到a中使h变量无效,但我仍然可以通过裸指针获取原始变量的值,而我认为它不应该存在?
第二个例子
struct Boxed {
field: u64,
}
fn main(){
let mut f = std::ptr::null();
{
let boxed = Box::new(Boxed{field: 123});
f = &boxed.field as *const u64;
}
println!("addr of f {:?}\nvalue {:?}", f, unsafe {&*f});
}
结果
addr of f 0x7fc1f8c05d30
value 123
我创建了一个包装值,并在使用后丢弃它,使用原始指针保存其地址,然后我仍然可以通过原始指针读取其字段的值。
因此,我的疑惑是:
1. 在Rust中,move操作实际上是memcpy吗?原始变量只是被编译器“隐藏”了吗? 2. Rust什么时候实际释放堆上变量的内存?(第二个示例)
谢谢!
我阅读过的内容: How does Rust provide move semantics?
Drop::drop()
时,内存将被释放。这并不意味着内存已被清理,只是标记为未来分配而已(或更少见地,返回给操作系统供其他程序使用)。 - user4815162342