如何分配 DST 结构体

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

我正在尝试分配夏令时,但我开始注意到一个问题。

allocate_zeroed
函数返回一个
[u8]
,它是一个具有整个结构体大小的胖指针。我将其转换为胖指针
*mut DST
,它将胖指针大小重新解释为数据大小。这是不正确的;我希望胖指针大小代表数据大小,而不是整个 DST 的大小(以字节为单位)。

use std::alloc::{Allocator, Global, Layout};

#[repr(C)]
struct DST {
    other_data: usize,
    other_data2: usize,
    other_data3: usize,
    other_data4: usize,
    data: [u8],
}


unsafe fn create(data_size: usize) {
    let fat_ptr = Global
        .allocate_zeroed(Layout::from_size_align((size_of::<usize>() * 4) + data_size, 8).unwrap())
        .unwrap()
        .as_ptr() as *mut DST;
    assert_eq!((*fat_ptr).data.len(), data_size + size_of::<usize>() * 4); // Pass
    assert_eq!((*fat_ptr).data.len(), data_size); // Failed
}

我想将胖指针大小(如果可能的话)更改为

data_size
。或者使胖指针具有正确的大小。

rust
1个回答
0
投票

您所目睹的行为记录在 Rust 参考关于类型转换表达式的部分中,在 指针到指针转换(已添加强调)下:

*const T
/
*mut T
可以通过以下行为转换为
*const U
/
*mut U

[ deletia ]

  • 如果

    T
    U
    都未调整大小,则指针也会原样返回。特别是,元数据被准确保留

    例如,从

    *const [T]
    *const [U]
    的转换会保留元素的数量。请注意,因此,此类转换不一定保留指针所指对象的大小(例如,将
    *const [u16]
    转换为
    *const [u8]
    将产生一个原始指针,该指针引用的对象的大小是原始指针的一半)。这同样适用于
    str
    以及未调整大小尾部为切片类型的任何复合类型,例如
    struct Foo(i32, [u8])
    (u64, Foo)

相反,您必须首先手动创建一个具有结构正确元数据的指针。

在稳定的 Rust 上,这可以使用例如来完成

std::ptr::slice_from_raw_parts_mut
在夜间 Rust 中使用
ptr_metadata
功能时,您可以通过
std::ptr::from_raw_parts_mut
更直接地进行操作。

另请注意,您的布局计算不正确,因为您忽略了填充(字段之间和结果结构之间的填充)。

Playground 链接到工作版本:stablenightly

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