about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-12-23 00:07:44 +0800
committerkennytm <kennytm@gmail.com>2018-12-23 02:12:03 +0800
commit22dfa2b44a797b76f38b9ce775da9bc9886787af (patch)
treedf69d3d8380cd9752247a36b904251c8fd5b9b07
parent1c76a2fd10adb737688e40564b6f4f35829fcab2 (diff)
parentb2d8040e6f89318c0ca7f5512ca31f8311b14a36 (diff)
downloadrust-22dfa2b44a797b76f38b9ce775da9bc9886787af.tar.gz
rust-22dfa2b44a797b76f38b9ce775da9bc9886787af.zip
Rollup merge of #56970 - Firstyear:mem_uninit_doc_ptr_drop, r=Manishearth
Mem uninit doc ptr drop

Extend the mem::uninitialized documentation to account for partially initialized arrays and how to correctly handle these. These are used in some datastructures (trees for example) or in FFI.

r? @Manishearth
-rw-r--r--src/libcore/mem.rs39
1 files changed, 39 insertions, 0 deletions
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index 0cde23cde40..87dde906601 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -530,6 +530,12 @@ pub unsafe fn zeroed<T>() -> T {
 /// 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`][drop_in_place] to remove the elements you have fully
+/// initialized followed by [`mem::forget`][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.
@@ -583,11 +589,44 @@ pub unsafe fn zeroed<T>() -> T {
 /// println!("{:?}", &data[0]);
 /// ```
 ///
+/// 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);
+/// ```
+///
 /// [`Vec`]: ../../std/vec/struct.Vec.html
 /// [`vec!`]: ../../std/macro.vec.html
 /// [`Clone`]: ../../std/clone/trait.Clone.html
 /// [ub]: ../../reference/behavior-considered-undefined.html
 /// [write]: ../ptr/fn.write.html
+/// [drop_in_place]: ../ptr/fn.drop_in_place.html
+/// [mem_zeroed]: fn.zeroed.html
+/// [mem_forget]: fn.forget.html
 /// [copy]: ../intrinsics/fn.copy.html
 /// [copy_no]: ../intrinsics/fn.copy_nonoverlapping.html
 /// [`Drop`]: ../ops/trait.Drop.html