gpt4 book ai didi

casting - 将 Vec 就地转换为 Vec 且开销最小

转载 作者:行者123 更新时间:2023-11-29 07:52:15 26 4
gpt4 key购买 nike

我正在尝试将 u32Vec 转换为 u8Vec,最好就地且没有太多开销。

我当前的解决方案依赖于不安全的代码来重新构造 Vec。有没有更好的方法来做到这一点,我的解决方案有哪些相关风险?

use std::mem;
use std::vec::Vec;

fn main() {
let mut vec32 = vec![1u32, 2];
let vec8;
unsafe {
let length = vec32.len() * 4; // size of u8 = 4 * size of u32
let capacity = vec32.capacity() * 4; // ^
let mutptr = vec32.as_mut_ptr() as *mut u8;
mem::forget(vec32); // don't run the destructor for vec32

// construct new vec
vec8 = Vec::from_raw_parts(mutptr, length, capacity);
}

println!("{:?}", vec8)
}

Rust Playground link

最佳答案

  1. 每当写 unsafe block ,我强烈鼓励人们在 block 上添加评论,解释为什么您认为代码实际上是安全的。这类信息对以后阅读代码的人很有用。

  2. 不要添加关于“魔数(Magic Number)”4 的注释,只需使用 mem::size_of::<u32> .我什至会使用 size_of对于 u8并执行除法以获得最大的清晰度。

  3. 您可以从 unsafe 返回新创建的 Vec阻止。

  4. 如评论中所述,像这样“转储”数据 block 会使数据格式平台相关;你会在小端和大端系统上得到不同的答案。这可能会导致将来出现大量调试问题。文件格式要么将平台字节序编码到文件中(使读者的工作更加困难),要么只将特定的字节顺序写入文件(使编写者的工作更加困难)。

  5. 我可能会移动整个 unsafe block 到一个函数并为其命名,仅用于组织目的。

  6. 您不需要导入 Vec ,在前奏。

use std::mem;

fn main() {
let mut vec32 = vec![1u32, 2];

// I copy-pasted this code from StackOverflow without reading the answer
// surrounding it that told me to write a comment explaining why this code
// is actually safe for my own use case.
let vec8 = unsafe {
let ratio = mem::size_of::<u32>() / mem::size_of::<u8>();

let length = vec32.len() * ratio;
let capacity = vec32.capacity() * ratio;
let ptr = vec32.as_mut_ptr() as *mut u8;

// Don't run the destructor for vec32
mem::forget(vec32);

// Construct new Vec
Vec::from_raw_parts(ptr, length, capacity)
};

println!("{:?}", vec8)
}

Playground

关于此代码,我最大的未知担忧在于与 Vec 关联的内存对齐。 .

Rust 的底层分配器 allocatesdeallocates具有特定 Layout 的内存。 Layout包含指针的大小对齐方式等信息。

我假设这段代码需要 Layout在对 alloc 的成对调用之间进行匹配和 dealloc .如果是这样的话,dropping the Vec<u8> constructed from a Vec<u32> might tell the allocator the wrong alignment因为该信息是 based on the element type .

如果没有更好的知识,“最好”的做法就是离开 Vec<u32>按原样简单地得到一个&[u8]给它。切片与分配器没有交互,避免了这个问题。

即使不与分配器交互,您也需要注意对齐!

另见:

关于casting - 将 Vec<u32> 就地转换为 Vec<u8> 且开销最小,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49690459/

26 4 0