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

介绍

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

Rust 死灵书相关的源码资料在github.com/anonymousGiga/Rustonomi...

主要内容

安全 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);
}
本作品采用《CC 协议》,转载必须注明作者和本文链接
令狐一冲
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!