rust - 是 Vec 中的数据吗总是密密麻麻?
问题描述
在 rust 中看到这个“快捷方式”代码是一种常见的模式:
unsafe fn any_as_u8_slice<T: Sized>(p: &T) -> &[u8] {
::std::slice::from_raw_parts(
(p as *const T) as *const u8,
::std::mem::size_of::<T>(),
)
}
IE。给定一个结构,不安全地将底层指针转换为&[u8]
以读取字节。
但是,在使用时采用相同的方法是否有效Vec<T>
?
例如,这似乎有效:
use std::mem::size_of;
use std::slice::from_raw_parts;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct Point {
pub x: u8,
pub y: u8,
pub z: u8,
}
fn as_bytes(data: &[Point]) -> &[u8] {
unsafe {
let raw_pointer = data.as_ptr();
from_raw_parts(raw_pointer as *const u8, size_of::<Point>() * data.len())
}
}
fn main() {
let points = vec![Point{x: 0u8, y: 1u8, z: 2u8}, Point{x: 3u8, y: 4u8, z: 5u8}];
let slice = points.as_slice();
println!("{:?}", slice);
let bytes = as_bytes(slice);
println!("{:?}", bytes);
assert!(bytes.len() == 6);
assert!(bytes[0] == 0u8);
assert!(bytes[1] == 1u8);
assert!(bytes[2] == 2u8);
assert!(bytes[3] == 3u8);
assert!(bytes[4] == 4u8);
assert!(bytes[5] == 5u8);
}
...但是假设以这种Vec<T>
方式表示为单个连续的数据块是否可靠?
https://doc.rust-lang.org/std/vec/struct.Vec.html#capacity-and-reallocation上的文档说:
如果 Vec 已分配内存,则它指向的内存位于堆上(由分配器定义,Rust 配置为默认使用),它的指针按顺序指向 len 初始化的连续元素(如果您将其强制为切片),然后是 capacity-len 逻辑上未初始化的连续元素。
...但我不确定我是否理解它的含义。这实际上是否意味着Vec<T>
底层指针指向一个长度size_of::<T>
* Vec 长度的内存块?
解决方案
是的,Vec<T>
可以将 a 制成可以被视为指向长度为的内存块的指针std::mem::size_of::<T>() times the length of Vec
。
有一个警告,因为您真正感兴趣的是slice
of T
,它Vec
可以提供;Vec
本身应该被认为是一个实现细节。除此之外:
A
Vec<T>
可以 deref到 slice[T]
。拿那个slice
。Rust 参考定义a与他们切片的
slice
部分具有相同的布局。Array
所以当我们从 aVec<T>
到 a[T]
时,这个长度切片n
保证与数组具有相同的内存布局[T; n]
。Rust 参考定义了 an的内存布局
Array
:数组的布局使得数组的第 n 个元素从数组的开头偏移
n * the size of the type
字节。数组的[T; n]
大小为size_of::<T>() * n
且对齐方式相同T
。我们知道
n
(来自[T]
)并且我们知道“the size of the type
字节”(通过mem::size_of<T>()
)。由于数组的所有成员必须始终完全初始化,并且鉴于上一段中的两个句子,我们知道访问所有字节是安全的,直到mem::size_of<T>() * length of Vec
(实际上长度为slice
,它引入了数组内存布局规则)。
为了利用这一切,你应该确保你得到了slice
第Vec
一个,as_ptr()
在切片上使用,并转换你得到的原始指针。这确保了上述定义的顺序。你fn as_bytes(data: &[Point]) -> &[u8]
是完全正确的。
推荐阅读
- kubernetes - 从 Red Hat Registry 拉取镜像的权限被拒绝
- ios - 使用 NSURLConnection 目标 c 连接到服务器
- cmake - 如何使用 qtcreator 通过 ninja 构建系统远程部署应用程序
- php - 字符串过滤器在 API 平台中不起作用
- javascript - 滚动时如何使元素粘在顶部
- xml - 如何从groovy中的xml中删除不是特定字段的节点?
- sql-server - 如何从表中获取最小入住时间和最大退房时间?
- wordpress - woocommerce BACS 添加自定义字段
- html - 如何将图像定位在 HTML/CSS 中的文本背景
- c# - 有没有办法以编程方式更改集合视图的默认项?