Function std::mem::uninitialized [] [src]

pub unsafe fn uninitialized<T>() -> T

Bypasses Rust's normal memory-initialization checks by pretending to produce a value of type T, while doing nothing at all.

This is incredibly dangerous, and should not be done lightly. Deeply consider initializing your memory with a default value instead.

This is useful for FFI functions and initializing arrays sometimes, but should generally be avoided.

Undefined Behavior

It is Undefined Behavior to read uninitialized memory. Even just an uninitialized boolean. For instance, if you branch on the value of such a boolean your program may take one, both, or neither of the branches.

Note that this often also includes writing to the uninitialized value. Rust believes the value is initialized, and will therefore try to Drop the uninitialized value and its fields if you try to overwrite the memory in a normal manner. The only way to safely initialize an arbitrary uninitialized value is with one of the ptr functions: write, copy, or copy_nonoverlapping. This isn't necessary if T is a primitive or otherwise only contains types that don't implement Drop.

If this value does need some kind of Drop, it must be initialized before it goes out of scope (and therefore would be dropped). Note that this includes a panic occurring and unwinding the stack suddenly.

Examples

Here's how to safely initialize an array of Vecs.

fn main() { use std::mem; use std::ptr; // Only declare the array. This safely leaves it // uninitialized in a way that Rust will track for us. // However we can't initialize it element-by-element // safely, and we can't use the `[value; 1000]` // constructor because it only works with `Copy` data. let mut data: [Vec<u32>; 1000]; unsafe { // So we need to do this to initialize it. data = mem::uninitialized(); // DANGER ZONE: if anything panics or otherwise // incorrectly reads the array here, we will have // Undefined Behavior. // It's ok to mutably iterate the data, since this // doesn't involve reading it at all. // (ptr and len are statically known for arrays) for elem in &mut data[..] { // *elem = Vec::new() would try to drop the // uninitialized memory at `elem` -- bad! // // Vec::new doesn't allocate or do really // anything. It's only safe to call here // because we know it won't panic. ptr::write(elem, Vec::new()); } // SAFE ZONE: everything is initialized. } println!("{:?}", &data[0]); }
use std::mem;
use std::ptr;

// Only declare the array. This safely leaves it
// uninitialized in a way that Rust will track for us.
// However we can't initialize it element-by-element
// safely, and we can't use the `[value; 1000]`
// constructor because it only works with `Copy` data.
let mut data: [Vec<u32>; 1000];

unsafe {
    // So we need to do this to initialize it.
    data = mem::uninitialized();

    // DANGER ZONE: if anything panics or otherwise
    // incorrectly reads the array here, we will have
    // Undefined Behavior.

    // It's ok to mutably iterate the data, since this
    // doesn't involve reading it at all.
    // (ptr and len are statically known for arrays)
    for elem in &mut data[..] {
        // *elem = Vec::new() would try to drop the
        // uninitialized memory at `elem` -- bad!
        //
        // Vec::new doesn't allocate or do really
        // anything. It's only safe to call here
        // because we know it won't panic.
        ptr::write(elem, Vec::new());
    }

    // SAFE ZONE: everything is initialized.
}

println!("{:?}", &data[0]);

This example emphasizes exactly how delicate and dangerous doing this is. Note that the vec! macro does let you initialize every element with a value that is only Clone, so the following is semantically equivalent and vastly less dangerous, as long as you can live with an extra heap allocation:

fn main() { let data: Vec<Vec<u32>> = vec![Vec::new(); 1000]; println!("{:?}", &data[0]); }
let data: Vec<Vec<u32>> = vec![Vec::new(); 1000];
println!("{:?}", &data[0]);