我正在尝试分配夏令时,但我开始注意到一个问题。
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 参考关于类型转换表达式的部分中,在 指针到指针转换(已添加强调)下:
/*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)
相反,您必须首先手动创建一个具有结构正确元数据的指针。
std::ptr::slice_from_raw_parts_mut
在夜间 Rust 中使用 ptr_metadata
功能时,您可以通过 std::ptr::from_raw_parts_mut
更直接地进行操作。
另请注意,您的布局计算不正确,因为您忽略了填充(字段之间和结果结构之间的填充)。