0
点赞
收藏
分享

微信扫一扫

018 Rust死灵书之非安全方式初始化内存


介绍

本系列录制的视频主要放在B站上​​Rust死灵书学习视频​​

Rust 死灵书相关的源码资料在https://github.com/anonymousGiga/Rustonomicon-Source

主要内容

安全 Rust 不允许部分地初始化数组,初始化一个数组时,通过let x = [val; N] 为每一个位置赋予相同的值,或者是单独指定每一个成员的值 let x = [val1, val2, val3]。但是有时我们需要用增量或者动态的方式初始化数组。

非安全 Rust 提供了mem::uninitialized处理这一问题。这个函数假装返回一个值,可以用它来欺骗 Rust 我们已经初始化了一个变量了。

特别注意

此方式会带来安全隐患。因为在Rust中,未被初始化的内存,赋值时是将字节拷贝到对应的内存;而对于被初始化过的内存,赋值时除了拷贝外还需要销毁原来的值。

解决方式,通过如下三个函数:

1、ptr::write(ptr, val) 函数接受 val 然后将它的值移入 ptr 指向的地址
2、ptr::copy(src, dest, count) 函数从 src 处将 count 个 T 占用的字节拷贝到 dest。(这个函数和 memmove 相同,不过要注意参数顺序是反的!)
3、ptr::copy_nonoverlapping(src, dest, count) 和 copy 的功能是一样的,不过它假设两段内存不会有重合部分,因此速度会略快一点。(这个函数和 memcpy 相同,不过要注意参数顺序是反的!)

//例子
use std::mem;
use std::ptr;

fn main() {
// 数组的大小是硬编码的但是可以很方便地修改
// 不过这表示我们不能用[a, b, c]这种方式初始化数组
const SIZE: usize = 3;

let mut x: [Box<u32>; SIZE];

x = [Box::new(1), Box::new(2), Box::new(3)];
//let y = [Box::new(2), Box::new(3), Box::new(4)];
x = y;

unsafe {
// 欺骗Rust说x已经被初始化
x = mem::uninitialized();
//x = y;//error,调用析构函数,再覆盖,但是x其实没有真正初始化

for i in 0..SIZE {
ptr::write(&mut x[i], Box::new(i as u32));
}
}

println!("{:?}", x);
}


举报

相关推荐

0 条评论