clarify rules for ZST Boxes
This commit is contained in:
parent
06a079c43e
commit
c555aabc5b
2 changed files with 14 additions and 2 deletions
|
@ -62,6 +62,11 @@
|
||||||
//! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the
|
//! T` obtained from [`Box::<T>::into_raw`] may be deallocated using the
|
||||||
//! [`Global`] allocator with [`Layout::for_value(&*value)`].
|
//! [`Global`] allocator with [`Layout::for_value(&*value)`].
|
||||||
//!
|
//!
|
||||||
|
//! For zero-sized values, the `Box` pointer still has to be [valid] for reads and writes and
|
||||||
|
//! sufficiently aligned. In particular, casting any aligned non-zero integer to a raw pointer
|
||||||
|
//! produces a valid pointer, but a pointer pointing into previously allocated memory that since got
|
||||||
|
//! freed is not valid.
|
||||||
|
//!
|
||||||
//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented
|
//! So long as `T: Sized`, a `Box<T>` is guaranteed to be represented
|
||||||
//! as a single pointer and is also ABI-compatible with C pointers
|
//! as a single pointer and is also ABI-compatible with C pointers
|
||||||
//! (i.e. the C type `T*`). This means that if you have extern "C"
|
//! (i.e. the C type `T*`). This means that if you have extern "C"
|
||||||
|
@ -125,6 +130,7 @@
|
||||||
//! [`Global`]: crate::alloc::Global
|
//! [`Global`]: crate::alloc::Global
|
||||||
//! [`Layout`]: crate::alloc::Layout
|
//! [`Layout`]: crate::alloc::Layout
|
||||||
//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
|
//! [`Layout::for_value(&*value)`]: crate::alloc::Layout::for_value
|
||||||
|
//! [valid]: ptr#safety
|
||||||
|
|
||||||
#![stable(feature = "rust1", since = "1.0.0")]
|
#![stable(feature = "rust1", since = "1.0.0")]
|
||||||
|
|
||||||
|
@ -385,7 +391,10 @@ impl<T: ?Sized> Box<T> {
|
||||||
/// memory problems. For example, a double-free may occur if the
|
/// memory problems. For example, a double-free may occur if the
|
||||||
/// function is called twice on the same raw pointer.
|
/// function is called twice on the same raw pointer.
|
||||||
///
|
///
|
||||||
|
/// The safety conditions are described in the [memory layout] section.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
|
///
|
||||||
/// Recreate a `Box` which was previously converted to a raw pointer
|
/// Recreate a `Box` which was previously converted to a raw pointer
|
||||||
/// using [`Box::into_raw`]:
|
/// using [`Box::into_raw`]:
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -16,12 +16,15 @@
|
||||||
//! provided at this point are very minimal:
|
//! provided at this point are very minimal:
|
||||||
//!
|
//!
|
||||||
//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst].
|
//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst].
|
||||||
//! * All pointers (except for the null pointer) are valid for all operations of
|
|
||||||
//! [size zero][zst].
|
|
||||||
//! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer
|
//! * For a pointer to be valid, it is necessary, but not always sufficient, that the pointer
|
||||||
//! be *dereferenceable*: the memory range of the given size starting at the pointer must all be
|
//! be *dereferenceable*: the memory range of the given size starting at the pointer must all be
|
||||||
//! within the bounds of a single allocated object. Note that in Rust,
|
//! within the bounds of a single allocated object. Note that in Rust,
|
||||||
//! every (stack-allocated) variable is considered a separate allocated object.
|
//! every (stack-allocated) variable is considered a separate allocated object.
|
||||||
|
//! * Even for operations of [size zero][zst], the pointer must not be "dangling" in the sense of
|
||||||
|
//! pointing to deallocated memory. However, casting any non-zero integer to a pointer is valid
|
||||||
|
//! for zero-sized accesses. This corresponds to writing your own allocator; allocating zero-sized
|
||||||
|
//! objects is not very hard. In contrast, when you use the standard allocator, after memory got
|
||||||
|
//! deallocated, even zero-sized accesses to that memory are invalid.
|
||||||
//! * All accesses performed by functions in this module are *non-atomic* in the sense
|
//! * All accesses performed by functions in this module are *non-atomic* in the sense
|
||||||
//! of [atomic operations] used to synchronize between threads. This means it is
|
//! of [atomic operations] used to synchronize between threads. This means it is
|
||||||
//! undefined behavior to perform two concurrent accesses to the same location from different
|
//! undefined behavior to perform two concurrent accesses to the same location from different
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue