gpt4 book ai didi

rust - 是否通过多个所有者修改单元>-UB?

转载 作者:行者123 更新时间:2023-12-03 11:39:58 25 4
gpt4 key购买 nike

我正在尝试使用较小版本的Rc,该版本将引用计数存储在指针中,并利用由于对齐而未使用的位。我怀疑我在造成UB,但我想知道确切的位置和原因。

基本上,这看起来像

struct SmallRc<T> {
inner: Cell<NonNull<T>>
}

构造函数分配 T并将其存储在指针处。
Clone的含义看起来-非常粗略-像
fn clone(&self) -> Self {
// Overflow-check within alignment-bits not shown
let cur = self.inner.get().as_ptr() as usize;
self.inner.set(unsafe { NonNull::new_unchecked((cur + 1) as *mut T) });
Self {
// This is where a new owner is created
// so there are now multiple owners of the same pointer
inner: self.inner.clone()
}
}
Drop -impl看起来几乎相同,再次解释为:
impl<T> Drop for SmallRc<T> {
fn drop(&mut self) {
// decrement the reference-counter similar as to how Clone does it.
self.dec_strong_count();
if self.strong_count() == 0 {
// drop and deallocate the inner value
}
}
}
Deref -impl屏蔽指针并取消对其的引用。本质上, Activity 的 &mut T永远不会超过一个。永远不要以未对齐的形式使用指针; cargo miri test通过。

所有这些都在一定程度上起作用。但是,以下测试失败
let rc = SmallRc::new(5u32);
assert_eq!(SmallRc::capacity(&rc), 3);
assert_eq!(SmallRc::strong_count(&rc), 1);
assert_eq!(*rc, 5);
let rc2 = rc.clone();
assert_eq!(SmallRc::strong_count(&rc), 2);
assert_eq!(SmallRc::strong_count(&rc2), 2);
assert_eq!(*rc2, 5);
drop(rc2);
assert_eq!(SmallRc::strong_count(&rc), 1); // Fails, reference count is still 2.

对此进行跟踪可以发现,虽然 Drop -impl减少了引用计数并将新的指针存储在 Cell中,但对 strong_count的最后一次调用使用了相同(旧)值,而根本没有从 Cell中读取数据。

我想知道为什么会这样。特别是因为 std::rc的实现大致相似;区别在于引用计数在指针后面的 Cell中,而此处我们为指针提供了 Cell

最佳答案

Rust中的Cell和相关类型(例如RefCellUnsafeCell)不是指针,它们只是提供内部可变性的包装器。因此,每个单个SmallRc值都将具有自己的Cell值,每个值都具有自己的NonNull指针。更改一个SmallRc值的指针不会影响其他指针,因为它们不共享数据。

另一方面,std::rc::Rc具有一个指向引用计数结构(NonNull<RcBox<T>>)的指针。指针本身永远不会改变,但是Rc值可以指向相同的引用计数结构,因此更改引用计数将影响指向同一结构的所有其他Rc值。

我正在想象您的SmallRc会像这样(注意clonedrop如何仅影响它们直接使用的值):

let rc = SmallRc::new(5u32);
// rc = { 0x12340001 } // <-- example pointer values
let rc2 = rc.clone();
// rc = { 0x12340002 }, rc2 = { 0x12340002 }
let rc3 = rc2.clone();
// rc = { 0x12340002 }, rc2 = { 0x12340003 }, rc3 = { 0x12340003 }
drop(rc2)
// rc = { 0x12340002 }, rc2 = [dropped], rc3 = { 0x12340003 }

关于rust - 是否通过多个所有者修改单元<NonNull <T >>-UB?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59456686/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com