@@ -253,21 +253,89 @@ pub unsafe fn dropped<T>() -> T {
253
253
dropped_impl ( )
254
254
}
255
255
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.
257
258
///
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.**
261
261
///
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.
263
282
///
264
283
/// # Examples
265
284
///
285
+ /// Here's how to safely initialize an array of `Vec`s.
286
+ ///
266
287
/// ```
267
288
/// use std::mem;
289
+ /// use std::ptr;
268
290
///
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]);
270
323
/// ```
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.
271
339
#[ inline]
272
340
#[ stable( feature = "rust1" , since = "1.0.0" ) ]
273
341
pub unsafe fn uninitialized < T > ( ) -> T {
0 commit comments