问题描述
考虑以下事项:
// 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) 结构可以像数组一样重新解释是否总是安全的?为什么?
数据指针对
mem::size_of::() * 4
有效,即S
的大小, 并正确对齐.The data pointer is valid for
mem::size_of::<T>() * 4
, which is the size ofS<T>
, and is properly aligned.- 所有项目都在同一个分配对象中,因为它们在同一个结构中.
- 指针不为空,因为它是从安全的
&self
参数转换而来的,并且它是正确对齐的,因为S
具有 (at至少)T
的对齐. - All of the items are in the same allocation object, because they are in the same struct.
- The pointer is not null, because it is a cast from the safe
&self
parameter, and it is properly aligned, becauseS<T>
has (at least) the alignment ofT
.
推荐答案
是的,它是安全且可移植的,除了非常大的 T
(修复如下).std 文档的安全部分中没有列出任何要点::slice::from_raw_parts 是这里的一个问题:
Yes, it is safe and portable, except for very large T
(fix below). None of the points listed in the safety section of the documentation for std::slice::from_raw_parts are a concern here:
data参数肯定指向4个连续初始化的T
s,因为S
被标记为#[repr(C)]
,这就是 C 在所有平台上的行为(repr(Rust)
不做这样的保证).
The data parameter definitely points to 4 consecutive initialized T
s, because S
is marked #[repr(C)]
, and that is the behavior of C on all platforms (repr(Rust)
makes no such guarantee).
引用的内存在引用的生命周期内不会发生变化,这是由借用检查器保证的.
The memory referenced is not mutated during the lifetime of the reference, which is guaranteed by the borrow checker.
切片的总大小不得大于isize::MAX
.代码不检查这个,所以它在技术上是一个安全漏洞.可以肯定的是,在 unsafe
之前添加对 as_slice
的检查:
The total size of the slice must not be greater than isize::MAX
. The code does not check this, so it is technically a safety hole. To be sure, add a check to as_slice
, before the unsafe
:
assert!(std::mem::size_of::<S<T>>() <= isize::MAX as _);
检查通常会被优化掉.
这篇关于将结构转换为数组是否合法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!