将结构转换为数组是否合法? [英] Is it legal to cast a struct to an array?

查看:60
本文介绍了将结构转换为数组是否合法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下事项:

// 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 是这里的一个问题:

    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:

    • 数据指针对mem::size_of::() * 4有效,即S的大小, 并正确对齐.

    • The data pointer is valid for mem::size_of::<T>() * 4, which is the size of S<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, because S<T> has (at least) the alignment of T.

    data参数肯定指向4个连续初始化的Ts,因为S被标记为#[repr(C)],这就是 C 在所有平台上的行为(repr(Rust) 不做这样的保证).

    The data parameter definitely points to 4 consecutive initialized Ts, 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 _);
    

    检查通常会被优化掉.

    这篇关于将结构转换为数组是否合法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆