通过原始指针克隆类型擦除的Arc是否安全?

问题描述 投票:4回答:1

我处于处理包装在Arc中的数据的情况,有时我最终会使用Arc来获取指向基础数据的原始指针。我的用例还要求类型擦除,因此原始指针通常被强制转换为into_raw,然后在重新构建into_raw时又强制转换为适当的具体类型。

我遇到了这样一种情况,即能够克隆*const c_void而无需了解基础数据的具体类型会很有用。据我了解,仅出于调用Arc的目的而使用伪类型重建Arc应该是安全的,只要我从未实际取消引用数据即可。因此,例如,这应该是安全的:

Arc

我遗漏了什么东西,使它实际上不安全?另外,我认为答案也适用于clone,但是如果有任何差异,请告诉我!

rust unsafe type-erasure raw-pointer
1个回答
0
投票

实际上,这“可能”是安全的,但您对此不做任何保证,也没有可移植性:

pub unsafe fn clone_raw(handle: *const c_void) -> *const c_void { let original = Arc::from_raw(handle); let copy = original.clone(); mem::forget(original); Arc::into_raw(copy) } 只是指向大致看起来像堆分配的结构的指针

Rc

Arc<T>给您指向struct ArcInner<T> { strong: atomic::AtomicUsize, weak: atomic::AtomicUsize, data: T, } 元素的指针。 into_raw()的实现采用这样的指针,assumes是指向dataArc::from_raw()元素的指针,在内存中返回并在assumes中找到一个data 。此假设取决于ArcInner<T>的内存布局,尤其是对齐方式。如果您在ArcInner<T>上调用T,然后像在into_rawArcInner<U>对齐方式不同的from_raw一样调用ArcInner<V>,则对U / V的位置进行偏移计算放在U中将是错误的,整个事情都会崩溃。

实际上,这很可能不会出现问题:由于V是两个ArcInner元素之后的第三个元素,因此任何data都可能以相同的方式对齐。但是,如果更改了stdlib的实现,则重建由usizeT的内存布局不同的Arc<V>::from_raw创建的Arc<U>将是不安全的,并且会崩溃。

© www.soinside.com 2019 - 2024. All rights reserved.