Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit 253c26b

Browse files
authoredMay 21, 2019
Rollup merge of rust-lang#60963 - blkerby:boxed_docs, r=alexcrichton
Update boxed::Box docs on memory layout The existing docs for the `Box` type state that "the way `Box` allocates and releases memory is unspecified", and that therefore the only valid pointer to pass to `Box::from_raw` is one obtained from `Box::into_raw`. This is inconsistent with the module-level docs which specify, > It is valid to convert both ways between a Box and a raw pointer allocated with the Global allocator, given that the Layout used with the allocator is correct for the type. More precisely, a value: *mut T that has been allocated with the Global allocator with Layout::for_value(&*value) may be converted into a box using Box::<T>::from_raw(value). Conversely, the memory backing a value: *mut T obtained from Box::<T>::into_raw may be deallocated using the Global allocator with Layout::for_value(&*value). This pull request updates the docs for `Box` to make them consistent with the module-level docs and adds some examples of how to use the global allocator in conjunction with `Box::from_raw` and `Box::into_raw`.
2 parents 0650084 + 4e37785 commit 253c26b

File tree

1 file changed

+64
-25
lines changed

1 file changed

+64
-25
lines changed
 

‎src/liballoc/boxed.rs

+64-25
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,6 @@
44
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
55
//! drop their contents when they go out of scope.
66
//!
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-
//!
177
//! # Examples
188
//!
199
//! Move a value from the stack to the heap by creating a [`Box`]:
@@ -61,6 +51,19 @@
6151
//! for a `Cons`. By introducing a `Box`, which has a defined size, we know how
6252
//! big `Cons` needs to be.
6353
//!
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+
//!
6467
//! [dereferencing]: ../../std/ops/trait.Deref.html
6568
//! [`Box`]: struct.Box.html
6669
//! [`Global`]: ../alloc/struct.Global.html
@@ -127,24 +130,38 @@ impl<T: ?Sized> Box<T> {
127130
///
128131
/// After calling this function, the raw pointer is owned by the
129132
/// 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
134138
///
135139
/// This function is unsafe because improper use may lead to
136140
/// memory problems. For example, a double-free may occur if the
137141
/// function is called twice on the same raw pointer.
138142
///
139-
/// [`Box::into_raw`]: struct.Box.html#method.into_raw
140-
///
141143
/// # Examples
142-
///
144+
/// Recreate a `Box` which was previously converted to a raw pointer
145+
/// using [`Box::into_raw`]:
143146
/// ```
144147
/// let x = Box::new(5);
145148
/// let ptr = Box::into_raw(x);
146149
/// let x = unsafe { Box::from_raw(ptr) };
147150
/// ```
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
148165
#[stable(feature = "box_raw", since = "1.4.0")]
149166
#[inline]
150167
pub unsafe fn from_raw(raw: *mut T) -> Self {
@@ -157,22 +174,40 @@ impl<T: ?Sized> Box<T> {
157174
///
158175
/// After calling this function, the caller is responsible for the
159176
/// 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.
163182
///
164183
/// Note: this is an associated function, which means that you have
165184
/// to call it as `Box::into_raw(b)` instead of `b.into_raw()`. This
166185
/// is so that there is no conflict with a method on the inner type.
167186
///
168-
/// [`Box::from_raw`]: struct.Box.html#method.from_raw
169-
///
170187
/// # Examples
171-
///
188+
/// Converting the raw pointer back into a `Box` with [`Box::from_raw`]
189+
/// for automatic cleanup:
172190
/// ```
173-
/// let x = Box::new(5);
191+
/// let x = Box::new(String::from("Hello"));
174192
/// 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:
175197
/// ```
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
176211
#[stable(feature = "box_raw", since = "1.4.0")]
177212
#[inline]
178213
pub fn into_raw(b: Box<T>) -> *mut T {
@@ -184,7 +219,7 @@ impl<T: ?Sized> Box<T> {
184219
/// After calling this function, the caller is responsible for the
185220
/// memory previously managed by the `Box`. In particular, the
186221
/// 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
188223
/// into a raw pointer and back into a `Box` with the [`Box::from_raw`]
189224
/// function.
190225
///
@@ -203,6 +238,10 @@ impl<T: ?Sized> Box<T> {
203238
/// fn main() {
204239
/// let x = Box::new(5);
205240
/// 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()) };
206245
/// }
207246
/// ```
208247
#[unstable(feature = "box_into_raw_non_null", issue = "47336")]

0 commit comments

Comments
 (0)