@@ -253,21 +253,89 @@ pub unsafe fn dropped<T>() -> T {
253253 dropped_impl ( )
254254}
255255
256- /// Creates an uninitialized value.
256+ /// Bypasses Rust's normal memory-initialization checks by pretending to
257+ /// produce a value of type T, while doing nothing at all.
257258///
258- /// Care must be taken when using this function, if the type `T` has a destructor and the value
259- /// falls out of scope (due to unwinding or returning) before being initialized, then the
260- /// destructor will run on uninitialized data, likely leading to crashes.
259+ /// **This is incredibly dangerous, and should not be done lightly. Deeply
260+ /// consider initializing your memory with a default value instead.**
261261///
262- /// This is useful for FFI functions sometimes, but should generally be avoided.
262+ /// This is useful for FFI functions and initializing arrays sometimes,
263+ /// but should generally be avoided.
264+ ///
265+ /// # Undefined Behaviour
266+ ///
267+ /// It is Undefined Behaviour to read uninitialized memory. Even just an
268+ /// uninitialized boolean. For instance, if you branch on the value of such
269+ /// a boolean your program may take one, both, or neither of the branches.
270+ ///
271+ /// Note that this often also includes *writing* to the uninitialized value.
272+ /// Rust believes the value is initialized, and will therefore try to Drop
273+ /// the uninitialized value and its fields if you try to overwrite the memory
274+ /// in a normal manner. The only way to safely initialize an arbitrary
275+ /// uninitialized value is with one of the `ptr` functions: `write`, `copy`, or
276+ /// `copy_nonoverlapping`. This isn't necessary if `T` is a primitive
277+ /// or otherwise only contains types that don't implement Drop.
278+ ///
279+ /// If this value *does* need some kind of Drop, it must be initialized before
280+ /// it goes out of scope (and therefore would be dropped). Note that this
281+ /// includes a `panic` occurring and unwinding the stack suddenly.
263282///
264283/// # Examples
265284///
285+ /// Here's how to safely initialize an array of `Vec`s.
286+ ///
266287/// ```
267288/// use std::mem;
289+ /// use std::ptr;
268290///
269- /// let x: i32 = unsafe { mem::uninitialized() };
291+ /// // Only declare the array. This safely leaves it
292+ /// // uninitialized in a way that Rust will track for us.
293+ /// // However we can't initialize it element-by-element
294+ /// // safely, and we can't use the `[value; 1000]`
295+ /// // constructor because it only works with `Copy` data.
296+ /// let mut data: [Vec<u32>; 1000];
297+ ///
298+ /// unsafe {
299+ /// // So we need to do this to initialize it.
300+ /// data = mem::uninitialized();
301+ ///
302+ /// // DANGER ZONE: if anything panics or otherwise
303+ /// // incorrectly reads the array here, we will have
304+ /// // Undefined Behaviour.
305+ ///
306+ /// // It's ok to mutably iterate the data, since this
307+ /// // doesn't involve reading it at all.
308+ /// // (ptr and len are statically known for arrays)
309+ /// for elem in &mut data[..] {
310+ /// // *elem = Vec::new() would try to drop the
311+ /// // uninitialized memory at `elem` -- bad!
312+ /// //
313+ /// // Vec::new doesn't allocate or do really
314+ /// // anything. It's only safe to call here
315+ /// // because we know it won't panic.
316+ /// ptr::write(elem, Vec::new());
317+ /// }
318+ ///
319+ /// // SAFE ZONE: everything is initialized.
320+ /// }
321+ ///
322+ /// println!("{:?}", &data[0]);
270323/// ```
324+ ///
325+ /// Hopefully this example emphasizes to you exactly how delicate
326+ /// and dangerous doing this is. Note that the `vec!` macro
327+ /// *does* let you initialize every element with a value that
328+ /// is only `Clone`, so the following is equivalent and vastly
329+ /// less dangerous, as long as you can live with an extra heap
330+ /// allocation:
331+ ///
332+ /// ```
333+ /// let data: Vec<Vec<u32>> = vec![Vec::new(); 1000];
334+ /// println!("{:?}", &data[0]);
335+ /// ```
336+ ///
337+ /// For large arrays this is probably advisable
338+ /// anyway to avoid blowing the stack.
271339#[ inline]
272340#[ stable( feature = "rust1" , since = "1.0.0" ) ]
273341pub unsafe fn uninitialized < T > ( ) -> T {
0 commit comments