@@ -58,7 +58,9 @@ pub use crate::intrinsics::transmute;
5858///
5959/// # Examples
6060///
61- /// Leak an I/O object, never closing the file:
61+ /// The canonical safe use of `mem::forget` is to circumvent a value's destructor
62+ /// implemented by the `Drop` trait. For example, this will leak a `File`, i.e. reclaim
63+ /// the space taken by the variable but never close the underlying system resource:
6264///
6365/// ```no_run
6466/// use std::mem;
@@ -68,27 +70,40 @@ pub use crate::intrinsics::transmute;
6870/// mem::forget(file);
6971/// ```
7072///
71- /// The practical use cases for `forget` are rather specialized and mainly come
72- /// up in unsafe or FFI code. For example:
73+ /// This is useful when the ownership of the underlying was previously
74+ /// transferred to code outside of Rust, for example by transmitting the raw
75+ /// file descriptor to C code.
76+ ///
77+ /// # Relationship with `ManuallyDrop`
78+ ///
79+ /// Using `mem::forget` to transmit memory ownership is error-prone and is best
80+ /// replaced with `ManuallyDrop`. Consider, for example, this code:
7381///
7482/// ```
7583/// use std::mem;
7684///
7785/// let mut v = vec![65, 122];
7886/// // Build a `String` using the contents of `v`
7987/// let s = unsafe { String::from_raw_parts(v.as_mut_ptr(), 2, v.capacity()) };
80- /// // immediately leak `v` because its memory is now managed by `s`
81- /// mem::forget(v);
88+ /// // leak `v` because its memory is now managed by `s`
89+ /// mem::forget(v); // ERROR - v is invalid and must not be passed to a function
8290/// assert_eq!(s, "Az");
8391/// // `s` is implicitly dropped and its memory deallocated.
8492/// ```
8593///
86- /// The above is correct, but brittle. If code gets added between the construction of
87- /// `String` and the invocation of `mem::forget()`, a panic within it will cause a double
88- /// free because the same memory is handled by both `v` and `s`. This can be fixed by
89- /// storing the result of `v.as_mut_ptr()` in a local variable and calling `mem::forget()`
90- /// before `String::from_raw_parts`. This kind of issue can be more robustly prevented by
91- /// using [`ManuallyDrop`], which is usually preferred for such cases:
94+ /// There are two issues with the above example:
95+ ///
96+ /// * If more code were added between the construction of `String` and the invocation of
97+ /// `mem::forget()`, a panic within it would cause a double free because the same memory
98+ /// is handled by both `v` and `s`.
99+ /// * After calling `v.as_mut_ptr()` and transmitting the ownership of the data to `s`,
100+ /// the `v` value is invalid. Although moving a value to `mem::forget` (which won't
101+ /// inspect it) seems safe, some types have strict requirements on their values that
102+ /// make them invalid when dangling or no longer owned. Using invalid values in any
103+ /// way, including passing them to or returning them from functions, constitutes
104+ /// undefined behavior and may break the assumptions made by the compiler.
105+ ///
106+ /// Switching to `ManuallyDrop` avoids both issues:
92107///
93108/// ```
94109/// use std::mem::ManuallyDrop;
@@ -108,12 +123,15 @@ pub use crate::intrinsics::transmute;
108123///
109124/// `ManuallyDrop` robustly prevents double-free because we disable `v`'s destructor
110125/// before doing anything else. `mem::forget()` doesn't allow this because it consumes its
111- /// argument, forcing us to call it only after extracting anything we need from `v`.
112- ///
113- /// Note that the above code cannot panic between construction of `ManuallyDrop` and
114- /// building the string. But even if it could (after a modification), a panic there would
115- /// result in a leak and not a double free. In other words, `ManuallyDrop` errs on the
116- /// side of leaking instead of erring on the side of dropping.
126+ /// argument, forcing us to call it only after extracting anything we need from `v`. Even
127+ /// if a panic were introduced between construction of `ManuallyDrop` and building the
128+ /// string (which cannot happen in the code as shown), it would result in a leak and not a
129+ /// double free. In other words, `ManuallyDrop` errs on the side of leaking instead of
130+ /// erring on the side of dropping.
131+ ///
132+ /// Also, `ManuallyDrop` prevents us from having to "touch" `v` after transferring the
133+ /// ownership to `s` - the final step of interacting with `v` to dispoe of it without
134+ /// running its destructor is entirely avoided.
117135///
118136/// [drop]: fn.drop.html
119137/// [uninit]: fn.uninitialized.html
0 commit comments