考虑以下:
// Just a sequence of adjacent fields of same the type
#[repr(C)]
#[derive(Debug)]
struct S<T> {
a : T,
b : T,
c : T,
d : T,
}
impl<T : Sized> S<T> {
fn new(a : T, b : T, c : T, d : T) -> Self {
Self {
a,
b,
c,
d,
}
}
// reinterpret it as an array
fn as_slice(&self) -> &[T] {
unsafe { std::slice::from_raw_parts(self as *const Self as *const T, 4) }
}
}
fn main() {
let s = S::new(1, 2, 3, 4);
let a = s.as_slice();
println!("s :: {:?}\n\
a :: {:?}", s, a);
}
- 这段代码可以移植吗?
- 假设具有相同类型字段的 repr(C) 结构可以像数组一样重新解释是否总是安全的?为什么?
是的,它是安全且便携的,除了非常大的T
(修复如下)。文档安全部分中列出的所有要点均不适用std::slice::from_raw_parts https://doc.rust-lang.org/beta/std/slice/fn.from_raw_parts.html这里有一个问题:
-
数据指针的有效期为mem::size_of::<T>() * 4
,其大小为S<T>
,并且已正确对齐。
- 所有项目都位于同一分配对象中,因为它们位于同一结构中。
- 指针不为空,因为它是从安全中强制转换的
&self
参数,并且它已正确对齐,因为S<T>
(至少)具有以下对齐方式T
.
-
data参数肯定指向4个连续初始化的T
s,因为S
被标记#[repr(C)]
which 被定义为 https://doc.rust-lang.org/reference/type-layout.html#reprc-structs在您的结构中,不会引入填充。 (repr(Rust)
不做出此类保证)。
-
引用的内存在引用的生命周期内不会发生变化,这是由借用检查器保证的。
-
切片的总大小不得大于isize::MAX
。该代码不会检查这一点,因此从技术上讲这是一个安全漏洞。为了确保安全,请添加一个检查as_slice
, 之前unsafe
:
assert!(std::mem::size_of::<S<T>>() <= isize::MAX as _);
该检查通常会被优化掉。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)