rust - 变量被删除后如何释放?

标签 rust

我正在阅读"learn rust with entirely too many linked lists" 。 在第 2.7 章中,作者说“我们不能在释放后删除 Box 的内容”。一个值被删除后如何被释放?释放不会在 drop 的实现中发生吗?或者这些是不同的概念?

在某些情况下,作者正在解释为什么链表的特定实现不是尾递归的,因此无法被编译器优化。

链接列表:

pub struct List {
    head: Link,
}

enum Link {
    Empty,
    More(Box<Node>),
}

struct Node {
    elem: i32,
    next: Link,
}

删除实现:

impl Drop for List {
    fn drop(&mut self) {
        // NOTE: you can't actually explicitly call `drop` in real Rust code;
        // we're pretending to be the compiler!
        self.head.drop(); // tail recursive - good!
    }
}

impl Drop for Link {
    fn drop(&mut self) {
        match *self {
            Link::Empty => {} // Done!
            Link::More(ref mut boxed_node) => {
                boxed_node.drop(); // tail recursive - good!
            }
        }
    }
}

impl Drop for Box<Node> {
    fn drop(&mut self) {
        self.ptr.drop(); // uh oh, not tail recursive!
        deallocate(self.ptr);
    }
}

impl Drop for Node {
    fn drop(&mut self) {
        self.next.drop();
    }
}

最佳答案

Wouldn't the deallocation occur in the implementation of drop or are these separate concepts?

它们是不同的概念。在示例代码中,Drop表示“清理我的内容/拥有的资源”,deallocate意思是“将我实际存储的内存返回到池中”。

drop方法是通过引用现有实例来运行的。 The definition of drop actually says :

When this method has been called, self has not yet been deallocated. That only happens after the method is over. If this wasn’t the case, self would be a dangling reference.

因此,head 必须完全删除才能释放它。并且删除过程需要先删除列表中的所有节点,每个节点只有在删除完成后才会释放关联的节点,从而导致堆栈为 drop s,其中每个后跟 deallocate ,但毕竟是 dropdeallocates在它们上面的堆栈上完成。因为您无法执行单个 deallocate直到drop已经在整个堆栈中被调用(此时尾节点的drop返回并且尾节点是第一个释放的),它不能以尾递归方式实现。


旁注:这与您在 C++ 中尝试使用 std::shared_ptr 实现链表时看到的问题完全相同。或std::unique_ptr对于next指针。就像 Rust 一样,C++ 将销毁(清理对象内的资源)与释放(释放对象所占用的内存)区分开来。当 head unique_ptr被清除后,在它释放内存之前,它必须告诉“head + 1”来清除它自己的 unique_ptr ,这又告诉“head + 2”清除其unique_ptr等等。在每种情况下,销毁(通过析构函数)必须先于释放(对于堆分配的内容可能通过 operator delete 发生,或者只是由编译器收缩堆栈而不实际为堆栈分配的内容释放任何内存)。

关于rust - 变量被删除后如何释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/72204310/

相关文章:

rust - 与 Vec 相比,为什么 SmallVec 在存储具有生命周期的类型时具有不同的行为?

selenium-webdriver - 需要一个字段作为 Rust 特征的一部分

assembly - 如何从 Cargo 构建中获取 assembly 输出?

rust - 如何为我不拥有的类型实现我不拥有的特征?

string - 预期结构 `std::string::String`,找到结构 `std::str::Split`

winapi - 如何使用 winapi crate 为 Windows 制作托盘图标?

rust - Vec::len 的运行时复杂度是多少?

arrays - 什么是单行解决方案来获取切片中除最后一项之外的所有内容而不使用最后一项的索引?

rust - 如何在结构体方法中为 self 的类型添加别名?

Rust 正确的错误处理(自动从一种错误类型转换为另一种带有问号的错误类型)