4
4
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
5
5
//! drop their contents when they go out of scope.
6
6
//!
7
- //! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for
8
- //! its allocation. It is valid to convert both ways between a [`Box`] and a
9
- //! raw pointer allocated with the [`Global`] allocator, given that the
10
- //! [`Layout`] used with the allocator is correct for the type. More precisely,
11
- //! a `value: *mut T` that has been allocated with the [`Global`] allocator
12
- //! with `Layout::for_value(&*value)` may be converted into a box using
13
- //! `Box::<T>::from_raw(value)`. Conversely, the memory backing a `value: *mut
14
- //! T` obtained from `Box::<T>::into_raw` may be deallocated using the
15
- //! [`Global`] allocator with `Layout::for_value(&*value)`.
16
- //!
17
7
//! # Examples
18
8
//!
19
9
//! Move a value from the stack to the heap by creating a [`Box`]:
61
51
//! for a `Cons`. By introducing a `Box`, which has a defined size, we know how
62
52
//! big `Cons` needs to be.
63
53
//!
54
+ //! # Memory layout
55
+ //!
56
+ //! For non-zero-sized values, a [`Box`] will use the [`Global`] allocator for
57
+ //! its allocation. It is valid to convert both ways between a [`Box`] and a
58
+ //! raw pointer allocated with the [`Global`] allocator, given that the
59
+ //! [`Layout`] used with the allocator is correct for the type. More precisely,
60
+ //! a `value: *mut T` that has been allocated with the [`Global`] allocator
61
+ //! with `Layout::for_value(&*value)` may be converted into a box using
62
+ //! `Box::<T>::from_raw(value)`. Conversely, the memory backing a `value: *mut
63
+ //! T` obtained from `Box::<T>::into_raw` may be deallocated using the
64
+ //! [`Global`] allocator with `Layout::for_value(&*value)`.
65
+ //!
66
+ //!
64
67
//! [dereferencing]: ../../std/ops/trait.Deref.html
65
68
//! [`Box`]: struct.Box.html
66
69
//! [`Global`]: ../alloc/struct.Global.html
@@ -127,24 +130,38 @@ impl<T: ?Sized> Box<T> {
127
130
///
128
131
/// After calling this function, the raw pointer is owned by the
129
132
/// resulting `Box`. Specifically, the `Box` destructor will call
130
- /// the destructor of `T` and free the allocated memory. Since the
131
- /// way `Box` allocates and releases memory is unspecified, the
132
- /// only valid pointer to pass to this function is the one taken
133
- /// from another `Box` via the [`Box::into_raw`] function.
133
+ /// the destructor of `T` and free the allocated memory. For this
134
+ /// to be safe, the memory must have been allocated in accordance
135
+ /// with the [memory layout] used by `Box` .
136
+ ///
137
+ /// # Safety
134
138
///
135
139
/// This function is unsafe because improper use may lead to
136
140
/// memory problems. For example, a double-free may occur if the
137
141
/// function is called twice on the same raw pointer.
138
142
///
139
- /// [`Box::into_raw`]: struct.Box.html#method.into_raw
140
- ///
141
143
/// # Examples
142
- ///
144
+ /// Recreate a `Box` which was previously converted to a raw pointer
145
+ /// using [`Box::into_raw`]:
143
146
/// ```
144
147
/// let x = Box::new(5);
145
148
/// let ptr = Box::into_raw(x);
146
149
/// let x = unsafe { Box::from_raw(ptr) };
147
150
/// ```
151
+ /// Manually create a `Box` from scratch by using the global allocator:
152
+ /// ```
153
+ /// use std::alloc::{alloc, Layout};
154
+ ///
155
+ /// unsafe {
156
+ /// let ptr = alloc(Layout::new::<i32>()) as *mut i32;
157
+ /// *ptr = 5;
158
+ /// let x = Box::from_raw(ptr);
159
+ /// }
160
+ /// ```
161
+ ///
162
+ /// [memory layout]: index.html#memory-layout
163
+ /// [`Layout`]: ../alloc/struct.Layout.html
164
+ /// [`Box::into_raw`]: struct.Box.html#method.into_raw
148
165
#[ stable( feature = "box_raw" , since = "1.4.0" ) ]
149
166
#[ inline]
150
167
pub unsafe fn from_raw ( raw : * mut T ) -> Self {
@@ -157,22 +174,40 @@ impl<T: ?Sized> Box<T> {
157
174
///
158
175
/// After calling this function, the caller is responsible for the
159
176
/// memory previously managed by the `Box`. In particular, the
160
- /// caller should properly destroy `T` and release the memory. The
161
- /// proper way to do so is to convert the raw pointer back into a
162
- /// `Box` with the [`Box::from_raw`] function.
177
+ /// caller should properly destroy `T` and release the memory, taking
178
+ /// into account the [memory layout] used by `Box`. The easiest way to
179
+ /// do this is to convert the raw pointer back into a `Box` with the
180
+ /// [`Box::from_raw`] function, allowing the `Box` destructor to perform
181
+ /// the cleanup.
163
182
///
164
183
/// Note: this is an associated function, which means that you have
165
184
/// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This
166
185
/// is so that there is no conflict with a method on the inner type.
167
186
///
168
- /// [`Box::from_raw`]: struct.Box.html#method.from_raw
169
- ///
170
187
/// # Examples
171
- ///
188
+ /// Converting the raw pointer back into a `Box` with [`Box::from_raw`]
189
+ /// for automatic cleanup:
172
190
/// ```
173
- /// let x = Box::new(5 );
191
+ /// let x = Box::new(String::from("Hello") );
174
192
/// let ptr = Box::into_raw(x);
193
+ /// let x = unsafe { Box::from_raw(ptr) };
194
+ /// ```
195
+ /// Manual cleanup by explicitly running the destructor and deallocating
196
+ /// the memory:
175
197
/// ```
198
+ /// use std::alloc::{dealloc, Layout};
199
+ /// use std::ptr;
200
+ ///
201
+ /// let x = Box::new(String::from("Hello"));
202
+ /// let p = Box::into_raw(x);
203
+ /// unsafe {
204
+ /// ptr::drop_in_place(p);
205
+ /// dealloc(p as *mut u8, Layout::new::<String>());
206
+ /// }
207
+ /// ```
208
+ ///
209
+ /// [memory layout]: index.html#memory-layout
210
+ /// [`Box::from_raw`]: struct.Box.html#method.from_raw
176
211
#[ stable( feature = "box_raw" , since = "1.4.0" ) ]
177
212
#[ inline]
178
213
pub fn into_raw ( b : Box < T > ) -> * mut T {
@@ -184,7 +219,7 @@ impl<T: ?Sized> Box<T> {
184
219
/// After calling this function, the caller is responsible for the
185
220
/// memory previously managed by the `Box`. In particular, the
186
221
/// caller should properly destroy `T` and release the memory. The
187
- /// proper way to do so is to convert the `NonNull<T>` pointer
222
+ /// easiest way to do so is to convert the `NonNull<T>` pointer
188
223
/// into a raw pointer and back into a `Box` with the [`Box::from_raw`]
189
224
/// function.
190
225
///
@@ -203,6 +238,10 @@ impl<T: ?Sized> Box<T> {
203
238
/// fn main() {
204
239
/// let x = Box::new(5);
205
240
/// let ptr = Box::into_raw_non_null(x);
241
+ ///
242
+ /// // Clean up the memory by converting the NonNull pointer back
243
+ /// // into a Box and letting the Box be dropped.
244
+ /// let x = unsafe { Box::from_raw(ptr.as_ptr()) };
206
245
/// }
207
246
/// ```
208
247
#[ unstable( feature = "box_into_raw_non_null" , issue = "47336" ) ]
0 commit comments