将结构转换为数组是否合法?
Is it legal to cast a struct to an array?
考虑以下因素:
// 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 文档的安全部分中列出的要点中的 None 在这里是一个问题:
数据指针对 mem::size_of::<T>() * 4
有效,这是 S<T>
的大小,并且正确对齐。
- 所有项目都在同一个分配对象中,因为它们在同一个结构中。
- 指针不为空,因为它是从安全的
&self
参数转换过来的,并且正确对齐,因为 S<T>
具有(至少)[=11= 的对齐方式].
data参数肯定指向4个连续初始化的T
s,因为S
在你的struct中被标记为#[repr(C)]
which is defined such that, no将引入填充。 (repr(Rust)
不作此类保证)。
引用的内存在引用的生命周期内不会发生变化,这是由借用检查器保证的。
切片的总大小不得大于isize::MAX
。代码不会对此进行检查,因此从技术上讲这是一个安全漏洞。可以肯定的是,在 unsafe
:
之前添加对 as_slice
的检查
assert!(std::mem::size_of::<S<T>>() <= isize::MAX as _);
检查通常会被优化。
考虑以下因素:
// 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 文档的安全部分中列出的要点中的 None 在这里是一个问题:
数据指针对
mem::size_of::<T>() * 4
有效,这是S<T>
的大小,并且正确对齐。- 所有项目都在同一个分配对象中,因为它们在同一个结构中。
- 指针不为空,因为它是从安全的
&self
参数转换过来的,并且正确对齐,因为S<T>
具有(至少)[=11= 的对齐方式].
data参数肯定指向4个连续初始化的
T
s,因为S
在你的struct中被标记为#[repr(C)]
which is defined such that, no将引入填充。 (repr(Rust)
不作此类保证)。引用的内存在引用的生命周期内不会发生变化,这是由借用检查器保证的。
切片的总大小不得大于
之前添加对isize::MAX
。代码不会对此进行检查,因此从技术上讲这是一个安全漏洞。可以肯定的是,在unsafe
:as_slice
的检查assert!(std::mem::size_of::<S<T>>() <= isize::MAX as _);
检查通常会被优化。