Tho*_*ers 4 casting unsafe rust
我想一个转换Vec的u32s到一个Vec的u8S,最好就地并没有太多的开销.
我目前的解决方案依赖于不安全的代码来重新构建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)
}
Run Code Online (Sandbox Code Playgroud)
每当写一个unsafe块时,我强烈建议人们在块上添加注释,解释为什么你认为代码实际上是安全的.这种类型的信息对将来阅读代码的人很有用.
只需使用,而不是添加关于"幻数"4的评论mem::size_of::<u32>.我甚至会去那么远,使用size_of了u8和执行部门的最大清晰.
您可以从unsafe块中返回新创建的Vec .
正如评论中所提到的,"倾销"这样的数据块会使数据格式平台依赖 ; 你将在小端和大端系统上得到不同的答案.这可能导致未来的大量调试问题.文件格式要么将平台字节序编码到文件中(使读者的工作更难),要么只对文件写一个特定的endinanness(使作者的工作更难).
我可能unsafe会将整个块移动到一个函数并为其命名,仅用于组织目的.
你不需要导入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)
}
Run Code Online (Sandbox Code Playgroud)
我对此代码最大的未知担忧在于与内存关联的内存对齐Vec.
Rust的底层分配器使用特定的分配和释放内存.包含诸如指针的大小和对齐之类的信息.LayoutLayout
我认为这个代码需要Layout以成对调用之间的匹配alloc和dealloc.如果是这种情况,那么Vec<u8>从a中删除构造Vec<u32>可能会告诉分配器错误的对齐,因为该信息基于元素类型.
如果没有更好的知识,那么"最好的"事情就是离开现状Vec<u32>并简单地得到&[u8]它.切片与分配器没有交互,避免了这个问题.
也可以看看:
如果就地转换不是那么强制性的,这样的东西管理字节顺序控制并避免不安全块:
extern crate byteorder;
use byteorder::{WriteBytesExt, BigEndian};
fn main() {
let vec32: Vec<u32> = vec![0xaabbccdd, 2];
let mut vec8: Vec<u8> = vec![];
for elem in vec32 {
vec8.write_u32::<BigEndian>(elem).unwrap();
}
println!("{:?}", vec8);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
843 次 |
| 最近记录: |