在Rust中,Weak如何< T>知道内部值何时被删除?

3phpmpom  于 2023-05-07  发布在  其他
关注(0)|答案(1)|浏览(230)

std::rc::Weak<T>的定义如下:

pub struct Weak<T: ?Sized> {
    ptr: NonNull<RcBox<T>>,
}

在我的理解中,当没有更多的Rc<T>时,RcBox<T>将被释放,Weak<T>.ptr现在指向一个可能包含任何内容的位置。那么,当upgrade()Weak<T>上被调用时,它是如何知道指针现在无效的呢?
Weak<T>::upgrade的实现如下:

pub fn upgrade(&self) -> Option<Rc<T>> {
        let inner = self.inner()?;

        if inner.strong() == 0 {
            None
        } else {
            unsafe {
                inner.inc_strong();
                Some(Rc::from_inner(self.ptr))
            }
        }
    }

这是否意味着当没有Rc<T>时,RcBox<T>并没有真正释放?如果是这样的话,那不是会泄漏内存吗?

gywdnpxw

gywdnpxw1#

RcBox不会被销毁,直到没有强 * 或 * 弱指针剩余。
然而,当强计数达到零时,所包含的T被丢弃。这有效地破坏了所包含的T,但不会释放T本身的内存。这就是Weak知道内部值是否被删除的方式--如果在强计数为零时尝试将Weak升级为Rc,则操作失败并返回None
一旦弱计数也达到零,RcBox本身就被释放。所以,不存在内存泄漏。
请注意,许多类型(如StringVec)管理单独的堆分配。例如,如果您有一个Rc<Vec<_>>,当强计数达到零而弱计数没有达到零时,内部Vec的drop代码将运行并删除其拥有的所有元素,并释放用于存储它们的堆分配。Vec本身用来保存堆指针、长度和容量的内存 * 不 * 释放,因为它属于RcBox。只有当强计数和弱计数都达到零时,才释放该分配。

相关问题