1.0.0[−][src]Function std::mem::uninitialized
pub unsafe fn uninitialized<T>() -> T
use mem::MaybeUninit::uninitialized
instead
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.
Writing to the uninitialized value is similarly dangerous. Rust believes the
value is initialized, and will therefore try to Drop
the uninitialized
value and its fields if you try to overwrite it in a normal manner. The only way
to safely initialize an uninitialized value is with ptr::write
,
ptr::copy
, or ptr::copy_nonoverlapping
.
If the value does implement 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.
If you partially initialize an array, you may need to use
ptr::drop_in_place
to remove the elements you have fully
initialized followed by mem::forget
to prevent drop running
on the array. If a partially allocated array is dropped this will lead to
undefined behaviour.
Examples
Here's how to safely initialize an array of Vec
s.
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]);Run
This example emphasizes exactly how delicate and dangerous using mem::uninitialized
can be. 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:
let data: Vec<Vec<u32>> = vec![Vec::new(); 1000]; println!("{:?}", &data[0]);Run
This example shows how to handle partially initialized arrays, which could be found in low-level datastructures.
use std::mem; use std::ptr; // Count the number of elements we have assigned. let mut data_len: usize = 0; let mut data: [String; 1000]; unsafe { data = mem::uninitialized(); for elem in &mut data[0..500] { ptr::write(elem, String::from("hello")); data_len += 1; } // For each item in the array, drop if we allocated it. for i in &mut data[0..data_len] { ptr::drop_in_place(i); } } // Forget the data. If this is allowed to drop, you may see a crash such as: // 'mem_uninit_test(2457,0x7fffb55dd380) malloc: *** error for object // 0x7ff3b8402920: pointer being freed was not allocated' mem::forget(data);Run