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