|
16 | 16 | //!
|
17 | 17 | //! # Safety
|
18 | 18 | //!
|
19 |
| -//! Many functions in this module take raw pointers as arguments and dereference |
20 |
| -//! them. For this to be safe, these pointers must be valid. However, because |
21 |
| -//! rust does not yet have a formal memory model, determining whether an |
22 |
| -//! arbitrary pointer is valid for a given operation can be tricky. |
| 19 | +//! Many functions in this module take raw pointers as arguments and read from |
| 20 | +//! or write to them. For this to be safe, these pointers must be *valid*. |
| 21 | +//! Whether a pointer is valid depends on the operation it is used for |
| 22 | +//! (read or write), and the extent of the memory that is accessed (i.e., |
| 23 | +//! how many bytes are read/written). Most functions use `*mut T` and `*const T` |
| 24 | +//! to access only a single value, in which case the documentation omits the size |
| 25 | +//! and implicitly assumes it to be `size_of::<T>()` bytes. |
23 | 26 | //!
|
24 |
| -//! There are two types of operations on memory, reads and writes. A single |
25 |
| -//! pointer can be valid for any combination of these operations. For example, a |
26 |
| -//! pointer is not valid for writes if a `&mut` exists which [refers to the same |
27 |
| -//! memory][aliasing]. The set of operations for which a pointer argument must |
28 |
| -//! be valid is explicitly documented for each function. This is not strictly |
29 |
| -//! necessary for `*const` arguments, as they can only be used for reads and |
30 |
| -//! never for writes. |
31 |
| -//! |
32 |
| -//! Some functions (e.g. [`copy`]) take a single pointer but |
33 |
| -//! operate on many values. In this case, the function will state the size of |
34 |
| -//! the operation for which the pointer must be valid. For example, |
35 |
| -//! `copy::<T>(&src, &mut dst, 3)` requires `dst` to be valid for writes of |
36 |
| -//! `size_of::<T>() * 3` bytes. When the documentation requires that a pointer |
37 |
| -//! be valid for an operation but omits the size of that operation, the size is |
38 |
| -//! implied to be `size_of::<T>()` bytes. |
39 |
| -//! |
40 |
| -//! While we can't yet define whether an arbitrary pointer is a valid one, there |
| 27 | +//! While we can't yet define whether an arbitrary pointer is valid, there |
41 | 28 | //! are a few rules regarding validity:
|
42 | 29 | //!
|
43 |
| -//! * The result of casting a reference to a pointer is valid for as long as the |
44 |
| -//! underlying object is live. |
45 |
| -//! * A [null] pointer is *never* valid. |
| 30 | +//! * A [null] pointer is *never* valid, not even for accesses of [size zero][zst]. |
46 | 31 | //! * All pointers (except for the null pointer) are valid for all operations of
|
47 | 32 | //! [size zero][zst].
|
| 33 | +//! * The result of casting a reference to a pointer is valid for as long as the |
| 34 | +//! underlying object is live and no reference (just raw pointers) is used to |
| 35 | +//! access the same memory. |
48 | 36 | //!
|
49 | 37 | //! These axioms, along with careful use of [`offset`] for pointer arithmentic,
|
50 | 38 | //! are enough to correctly implement many useful things in unsafe code. Still,
|
|
60 | 48 | //! this requirement in their documentation. Notable exceptions to this are
|
61 | 49 | //! [`read_unaligned`] and [`write_unaligned`].
|
62 | 50 | //!
|
| 51 | +//! When a function requires proper alignment, it does so even if the access |
| 52 | +//! has size 0, i.e., even if memory is not actually touched. Consider using |
| 53 | +//! [`NonNull::dangling`] in such cases. |
| 54 | +//! |
63 | 55 | //! [aliasing]: ../../nomicon/aliasing.html
|
64 | 56 | //! [book]: ../../book/second-edition/ch19-01-unsafe-rust.html#dereferencing-a-raw-pointer
|
65 | 57 | //! [ub]: ../../reference/behavior-considered-undefined.html
|
|
69 | 61 | //! [`offset`]: ../../std/primitive.pointer.html#method.offset
|
70 | 62 | //! [`read_unaligned`]: ./fn.read_unaligned.html
|
71 | 63 | //! [`write_unaligned`]: ./fn.write_unaligned.html
|
| 64 | +//! [`NonNull::dangling`]: ./struct.NonNull.html#method.dangling |
72 | 65 |
|
73 | 66 | #![stable(feature = "rust1", since = "1.0.0")]
|
74 | 67 |
|
@@ -122,6 +115,8 @@ pub use intrinsics::write_bytes;
|
122 | 115 | /// again. [`write`] can be used to overwrite data without causing it to be
|
123 | 116 | /// dropped.
|
124 | 117 | ///
|
| 118 | +/// These restrictions apply even if `T` has size `0`. |
| 119 | +/// |
125 | 120 | /// [valid]: ../ptr/index.html#safety
|
126 | 121 | /// [`Copy`]: ../marker/trait.Copy.html
|
127 | 122 | /// [`write`]: ../ptr/fn.write.html
|
@@ -211,6 +206,8 @@ pub const fn null_mut<T>() -> *mut T { 0 as *mut T }
|
211 | 206 | ///
|
212 | 207 | /// * Both `x` and `y` must be properly aligned.
|
213 | 208 | ///
|
| 209 | +/// These restrictions apply even if `T` has size `0`. |
| 210 | +/// |
214 | 211 | /// [valid]: ../ptr/index.html#safety
|
215 | 212 | ///
|
216 | 213 | /// # Examples
|
@@ -278,6 +275,8 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
|
278 | 275 | /// size_of::<T>()` bytes must *not* overlap with the region of memory
|
279 | 276 | /// beginning at `y` with the same size.
|
280 | 277 | ///
|
| 278 | +/// These restrictions apply even if `T` has size `0`. |
| 279 | +/// |
281 | 280 | /// [valid]: ../ptr/index.html#safety
|
282 | 281 | ///
|
283 | 282 | /// # Examples
|
@@ -389,6 +388,8 @@ unsafe fn swap_nonoverlapping_bytes(x: *mut u8, y: *mut u8, len: usize) {
|
389 | 388 | ///
|
390 | 389 | /// * `dest` must be properly aligned.
|
391 | 390 | ///
|
| 391 | +/// These restrictions apply even if `T` has size `0`. |
| 392 | +/// |
392 | 393 | /// [valid]: ../ptr/index.html#safety
|
393 | 394 | ///
|
394 | 395 | /// # Examples
|
@@ -426,6 +427,8 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
|
426 | 427 | /// * `src` must be properly aligned. Use [`read_unaligned`] if this is not the
|
427 | 428 | /// case.
|
428 | 429 | ///
|
| 430 | +/// These restrictions apply even if `T` has size `0`. |
| 431 | +/// |
429 | 432 | /// ## Ownership of the Returned Value
|
430 | 433 | ///
|
431 | 434 | /// `read` creates a bitwise copy of `T`, regardless of whether `T` is [`Copy`].
|
@@ -540,6 +543,8 @@ pub unsafe fn read<T>(src: *const T) -> T {
|
540 | 543 | /// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the returned
|
541 | 544 | /// value and the value at `*src` can [violate memory safety][read-ownership].
|
542 | 545 | ///
|
| 546 | +/// These restrictions apply even if `T` has size `0`. |
| 547 | +/// |
543 | 548 | /// [`Copy`]: ../marker/trait.Copy.html
|
544 | 549 | /// [`read`]: ./fn.read.html
|
545 | 550 | /// [`write_unaligned`]: ./fn.write_unaligned.html
|
@@ -616,6 +621,8 @@ pub unsafe fn read_unaligned<T>(src: *const T) -> T {
|
616 | 621 | /// * `dst` must be properly aligned. Use [`write_unaligned`] if this is not the
|
617 | 622 | /// case.
|
618 | 623 | ///
|
| 624 | +/// These restrictions apply even if `T` has size `0`. |
| 625 | +/// |
619 | 626 | /// [valid]: ../ptr/index.html#safety
|
620 | 627 | /// [`write_unaligned`]: ./fn.write_unaligned.html
|
621 | 628 | ///
|
@@ -687,6 +694,8 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
|
687 | 694 | ///
|
688 | 695 | /// * `dst` must be [valid] for writes.
|
689 | 696 | ///
|
| 697 | +/// These restrictions apply even if `T` has size `0`. |
| 698 | +/// |
690 | 699 | /// [valid]: ../ptr/index.html#safety
|
691 | 700 | ///
|
692 | 701 | /// # Examples
|
@@ -770,6 +779,8 @@ pub unsafe fn write_unaligned<T>(dst: *mut T, src: T) {
|
770 | 779 | /// However, storing non-[`Copy`] types in volatile memory is almost certainly
|
771 | 780 | /// incorrect.
|
772 | 781 | ///
|
| 782 | +/// These restrictions apply even if `T` has size `0`. |
| 783 | +/// |
773 | 784 | /// [valid]: ../ptr/index.html#safety
|
774 | 785 | /// [`Copy`]: ../marker/trait.Copy.html
|
775 | 786 | /// [`read`]: ./fn.read.html
|
@@ -839,6 +850,8 @@ pub unsafe fn read_volatile<T>(src: *const T) -> T {
|
839 | 850 | ///
|
840 | 851 | /// * `dst` must be properly aligned.
|
841 | 852 | ///
|
| 853 | +/// These restrictions apply even if `T` has size `0`. |
| 854 | +/// |
842 | 855 | /// [valid]: ../ptr/index.html#safety
|
843 | 856 | ///
|
844 | 857 | /// Just like in C, whether an operation is volatile has no bearing whatsoever
|
|
0 commit comments