【问题标题】:If Rust is not garbage collected, how is memory cleaned / released? [duplicate]如果 Rust 没有被垃圾回收,那么内存是如何清理/释放的? [复制]
【发布时间】:2021-12-20 12:08:45
【问题描述】:

我在 rust 中看到了一个名为 drop(T) 的构建函数,基本上,它会移动给定的变量。

假设我们有如下代码:

struct Obj {
    a: i32,
}

impl Drop for Obj {
    fn drop(&mut self) {
        println!("> Dropping {}", self.a);
    }
}

fn main() {
    let mut m = &Obj { a: 5 };

    m = &Obj { a: 6 };
    m = &Obj { a: 7 };
    m = &Obj { a: 8 };

    let t = thread::spawn(|| {
        for i in 0..5 {
            println!("Counting {}", i);
            thread::sleep(Duration::from_secs_f32(1.0));
        }
    });
    t.join().unwrap();
}

结果是:

> Dropping 6
> Dropping 7
> Dropping 8
Counting 0
Counting 1
Counting 2
Counting 3
Counting 4
> Dropping 5

由于结果显示刚辞职后6到8就被收集了,所以起源5一直持续到main结束。为什么一开始就没有收集到 5?

【问题讨论】:

  • 在其范围结束时,该范围内拥有的所有内容都将被删除(“清理”)。
  • @Netwave 在代码的情况下,我可以在 main 结束前手动清理 Obj{5}
  • @Netwave 不会编译,你不能移出引用。
  • @EnXie 你可以保持它的名字(因为它是一个匿名的临时文件)并预先删除它的所有引用,但这不会做任何有用的事情,因为它没有实现Drop .
  • @Masklinn,是的,我实际上是在构建正确的答案。

标签: rust


【解决方案1】:

我认为编译器会插入这样的代码

fn main() {
    let mut _1 = Obj { a: 5 };
    let mut m = &_1;
    let mut _2 = Obj { a: 6 };
    m = &_2;

    drop(_1);
    drop(_2);
}

所以当退出 main 作用域时,原点 Obj 将下降

【讨论】:

  • 我已经尝试了 Drop Traits.. 发生了一些有趣的事情,你知道它是如何工作的吗?
  • 我不知道它是如何工作的。只记得之前看过一本书,介绍直接引用,编译后编译器会创建一个临时变量,然后这个临时变量被编译器操作。但我不知道编译器会用它做什么
【解决方案2】:

在范围结束后,范围内拥有的所有内容都将被删除(“清理”)。 在这种情况下,如果您想手动删除它,您可以,但需要将所有内容都明确显示给编译器:

struct Obj {
    a: i32,
}

fn main() {
    let obj_a = Obj { a: 5 }; // get an owned object
    let mut a = &obj_a; // use a reference to the object
    a = &Obj { a: 6 }; // change to another object reference
    drop(obj_a); // drop the original OWNED object manually
}

Playground

原来的 Obj 会怎样?

在您的情况下,您无法访问对象的拥有版本,因此它只是在范围的末尾被删除。但是您始终可以将它放在一个变量中,您可以在需要的任何时候手动删除它。

如果Rust没有GC,如何手动清理?

拥有数据上使用drop

关于更新的示例:

为什么一开始没有收集到 5 个?

编译器足够聪明,有时可以预见到您并没有真正使用那里的任何东西。我的解释是它正在尝试优化代码。

检查如果您手动删除 5 obj 会发生什么。

use std::thread;
use std::time::Duration;


struct Obj {
    a: i32,
}

impl Drop for Obj {
    fn drop(&mut self) {
        println!("> Dropping {}", self.a);
    }
}

fn main() {
    let obj = Obj { a: 5 };
    let mut m = &obj;

    m = &Obj { a: 6 };
    drop(obj);
    m = &Obj { a: 7 };
    m = &Obj { a: 8 };

    let t = thread::spawn(|| {
        for i in 0..5 {
            println!("Counting {}", i);
            thread::sleep(Duration::from_secs_f32(1.0));
        }
    });
    t.join().unwrap();
}

Playground

【讨论】:

  • 我更新了我的问题,Implement a Drop Traint 发生了一些有趣的事情。
  • @EnXie,我用你的新例子扩展了答案。但是请不要一直更新问题,通常最好打开一个新的相关问题:)
  • 知道了。下次我会做的。很多人
【解决方案3】:

Rust 所有权负责对象的生命周期。它在超出范围时被释放,除非moved 意味着释放它的责任传递给另一个范围。

尝试将Drop Traits 添加到您的对象以查看它何时被释放。

进一步阅读,

【讨论】:

  • 我已经尝试了 Drop Traits.. 发生了一些有趣的事情,我更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-02-10
  • 1970-01-01
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
  • 2021-06-12
  • 1970-01-01
相关资源
最近更新 更多