-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Rewrite docs for pointer methods #53783
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 30 commits
911d35f
da58beb
9f5a3cc
04a08c6
7b2ef6b
6f7338b
30122e9
e40585f
ea5570c
3a55c85
95a9088
7e165d9
c8da321
b0c5dc2
098bec8
fc63113
1ec66fb
e869b81
d97f61f
c06f551
2741224
18a7bdb
4ed469c
dc2237c
b463871
408a6a0
755de3c
bc809e0
78f5b68
c44e88c
2713d36
0ec87d0
adcc0d2
c197dc4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -962,59 +962,127 @@ extern "rust-intrinsic" { | |
/// value is not necessarily valid to be used to actually access memory. | ||
pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T; | ||
|
||
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source | ||
/// and destination may *not* overlap. | ||
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source | ||
/// and destination must *not* overlap. | ||
/// | ||
/// `copy_nonoverlapping` is semantically equivalent to C's `memcpy`. | ||
/// For regions of memory which might overlap, use [`copy`] instead. | ||
/// | ||
/// `copy_nonoverlapping` is semantically equivalent to C's [`memcpy`], but | ||
/// with the argument order swapped. | ||
/// | ||
/// [`copy`]: ./fn.copy.html | ||
/// [`memcpy`]: https://en.cppreference.com/w/c/string/byte/memcpy | ||
/// | ||
/// # Safety | ||
/// | ||
/// Beyond requiring that the program must be allowed to access both regions | ||
/// of memory, it is Undefined Behavior for source and destination to | ||
/// overlap. Care must also be taken with the ownership of `src` and | ||
/// `dst`. This method semantically moves the values of `src` into `dst`. | ||
/// However it does not drop the contents of `dst`, or prevent the contents | ||
/// of `src` from being dropped or used. | ||
/// Behavior is undefined if any of the following conditions are violated: | ||
/// | ||
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes. | ||
/// | ||
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes. | ||
/// | ||
/// * Both `src` and `dst` must be properly aligned. | ||
/// | ||
/// * The region of memory beginning at `src` with a size of `count * | ||
/// size_of::<T>()` bytes must *not* overlap with the region of memory | ||
/// beginning at `dst` with the same size. | ||
/// | ||
/// Like [`read`], `copy_nonoverlapping` creates a bitwise copy of `T`, regardless of | ||
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using *both* the values | ||
/// in the region beginning at `*src` and the region beginning at `*dst` can | ||
/// [violate memory safety][read-ownership]. | ||
/// | ||
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is | ||
/// `0`, the pointers must be non-NULL and properly aligned. | ||
/// | ||
/// [`Copy`]: ../marker/trait.Copy.html | ||
/// [`read`]: ../ptr/fn.read.html | ||
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value | ||
/// [valid]: ../ptr/index.html#safety | ||
/// | ||
/// # Examples | ||
/// | ||
/// A safe swap function: | ||
/// Manually implement [`Vec::append`]: | ||
/// | ||
/// ``` | ||
/// use std::mem; | ||
/// use std::ptr; | ||
/// | ||
/// # #[allow(dead_code)] | ||
/// fn swap<T>(x: &mut T, y: &mut T) { | ||
/// unsafe { | ||
/// // Give ourselves some scratch space to work with | ||
/// let mut t: T = mem::uninitialized(); | ||
/// /// Moves all the elements of `src` into `dst`, leaving `src` empty. | ||
/// fn append<T>(dst: &mut Vec<T>, src: &mut Vec<T>) { | ||
/// let src_len = src.len(); | ||
/// let dst_len = dst.len(); | ||
/// | ||
/// // Perform the swap, `&mut` pointers never alias | ||
/// ptr::copy_nonoverlapping(x, &mut t, 1); | ||
/// ptr::copy_nonoverlapping(y, x, 1); | ||
/// ptr::copy_nonoverlapping(&t, y, 1); | ||
/// // Ensure that `dst` has enough capacity to hold all of `src`. | ||
/// dst.reserve(src_len); | ||
/// | ||
/// // y and t now point to the same thing, but we need to completely forget `t` | ||
/// // because it's no longer relevant. | ||
/// mem::forget(t); | ||
/// unsafe { | ||
/// // The call to offset is always safe because `Vec` will never | ||
/// // allocate more than `isize::MAX` bytes. | ||
/// let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize); | ||
/// let src_ptr = src.as_ptr(); | ||
/// | ||
/// // Truncate `src` without dropping its contents. We do this first, | ||
/// // to avoid problems in case something further down panics. | ||
/// src.set_len(0); | ||
/// | ||
/// // The two regions cannot overlap becuase mutable references do | ||
/// // not alias, and two different vectors cannot own the same | ||
/// // memory. | ||
/// ptr::copy_nonoverlapping(src_ptr, dst_ptr, src_len); | ||
/// | ||
/// // Notify `dst` that it now holds the contents of `src`. | ||
/// dst.set_len(dst_len + src_len); | ||
/// } | ||
/// } | ||
/// | ||
/// let mut a = vec!['r']; | ||
/// let mut b = vec!['u', 's', 't']; | ||
/// | ||
/// append(&mut a, &mut b); | ||
/// | ||
/// assert_eq!(a, &['r', 'u', 's', 't']); | ||
/// assert!(b.is_empty()); | ||
/// ``` | ||
/// | ||
/// [`Vec::append`]: ../../std/vec/struct.Vec.html#method.append | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize); | ||
|
||
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source | ||
/// Copies `count * size_of::<T>()` bytes from `src` to `dst`. The source | ||
/// and destination may overlap. | ||
/// | ||
/// `copy` is semantically equivalent to C's `memmove`. | ||
/// If the source and destination will *never* overlap, | ||
/// [`copy_nonoverlapping`] can be used instead. | ||
/// | ||
/// `copy` is semantically equivalent to C's [`memmove`], but with the argument | ||
/// order swapped. Copying takes place as if the bytes were copied from `src` | ||
/// to a temporary array and then copied from the array to `dst`. | ||
/// | ||
/// [`copy_nonoverlapping`]: ./fn.copy_nonoverlapping.html | ||
/// [`memmove`]: https://en.cppreference.com/w/c/string/byte/memmove | ||
/// | ||
/// # Safety | ||
/// | ||
/// Care must be taken with the ownership of `src` and `dst`. | ||
/// This method semantically moves the values of `src` into `dst`. | ||
/// However it does not drop the contents of `dst`, or prevent the contents of `src` | ||
/// from being dropped or used. | ||
/// Behavior is undefined if any of the following conditions are violated: | ||
/// | ||
/// * `src` must be [valid] for reads of `count * size_of::<T>()` bytes. | ||
/// | ||
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes. | ||
/// | ||
/// * Both `src` and `dst` must be properly aligned. | ||
/// | ||
/// Like [`read`], `copy` creates a bitwise copy of `T`, regardless of | ||
/// whether `T` is [`Copy`]. If `T` is not [`Copy`], using both the values | ||
/// in the region beginning at `*src` and the region beginning at `*dst` can | ||
/// [violate memory safety][read-ownership]. | ||
/// | ||
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is | ||
/// `0`, the pointers must be non-NULL and properly aligned. | ||
/// | ||
/// [`Copy`]: ../marker/trait.Copy.html | ||
/// [`read`]: ../ptr/fn.read.html | ||
/// [read-ownership]: ../ptr/fn.read.html#ownership-of-the-returned-value | ||
/// [valid]: ../ptr/index.html#safety | ||
/// | ||
/// # Examples | ||
/// | ||
|
@@ -1031,24 +1099,76 @@ extern "rust-intrinsic" { | |
/// dst | ||
/// } | ||
/// ``` | ||
/// | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
pub fn copy<T>(src: *const T, dst: *mut T, count: usize); | ||
|
||
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()` | ||
/// bytes of memory starting at `dst` to `val`. | ||
/// Sets `count * size_of::<T>()` bytes of memory starting at `dst` to | ||
/// `val`. | ||
/// | ||
/// `write_bytes` is similar to C's [`memset`], but sets `count * | ||
/// size_of::<T>()` bytes to `val`. | ||
/// | ||
/// [`memset`]: https://en.cppreference.com/w/c/string/byte/memset | ||
/// | ||
/// # Safety | ||
/// | ||
/// Behavior is undefined if any of the following conditions are violated: | ||
/// | ||
/// * `dst` must be [valid] for writes of `count * size_of::<T>()` bytes. | ||
/// | ||
/// * `dst` must be properly aligned. | ||
/// | ||
/// Additionally, the caller should ensure that writing `count * | ||
RalfJung marked this conversation as resolved.
Show resolved
Hide resolved
|
||
/// size_of::<T>()` bytes to the given region of memory results in a valid | ||
/// value of `T`. Using a region of memory typed as a `T` that contains an | ||
/// invalid value of `T` is undefined behavior. | ||
/// | ||
/// Note that even if the effectively copied size (`count * size_of::<T>()`) is | ||
/// `0`, the pointer must be non-NULL and properly aligned. | ||
/// | ||
/// [valid]: ../ptr/index.html#safety | ||
/// | ||
/// # Examples | ||
/// | ||
/// Basic usage: | ||
/// | ||
/// ``` | ||
/// use std::ptr; | ||
/// | ||
/// let mut vec = vec![0; 4]; | ||
/// let mut vec = vec![0u32; 4]; | ||
/// unsafe { | ||
/// let vec_ptr = vec.as_mut_ptr(); | ||
/// ptr::write_bytes(vec_ptr, b'a', 2); | ||
/// ptr::write_bytes(vec_ptr, 0xfe, 2); | ||
/// } | ||
/// assert_eq!(vec, [0xfefefefe, 0xfefefefe, 0, 0]); | ||
/// ``` | ||
/// | ||
/// Creating an invalid value: | ||
/// | ||
/// ``` | ||
/// use std::ptr; | ||
/// | ||
/// let mut v = Box::new(0i32); | ||
/// | ||
/// unsafe { | ||
/// // Leaks the previously held value by overwriting the `Box<T>` with | ||
/// // a null pointer. | ||
/// ptr::write_bytes(&mut v, 0, 1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not entirely sure what's going on here? Is it overwriting the pointer inside the Making this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My intention here was to demonstrate that creating an invalid value can result in UB later in the program, outside of the Rereading it now, it does seem a bit convoluted. Perhaps we could write an arbitrary value (instead of 0), or-- since There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I added the |
||
/// } | ||
/// assert_eq!(vec, [b'a', b'a', 0, 0]); | ||
/// | ||
/// // At this point, using or dropping `v` results in undefined behavior. | ||
/// // drop(v); // ERROR | ||
/// | ||
/// // Even leaking `v` "uses" it, and hence is undefined behavior. | ||
/// // mem::forget(v); // ERROR | ||
/// | ||
/// unsafe { | ||
/// // Let us instead put in a valid value | ||
/// ptr::write(&mut v, Box::new(42i32)); | ||
/// } | ||
/// | ||
/// // Now the box is fine | ||
/// assert_eq!(*v, 42); | ||
/// ``` | ||
#[stable(feature = "rust1", since = "1.0.0")] | ||
pub fn write_bytes<T>(dst: *mut T, val: u8, count: usize); | ||
|
@@ -1066,7 +1186,7 @@ extern "rust-intrinsic" { | |
/// `min_align_of::<T>()` | ||
/// | ||
/// The volatile parameter is set to `true`, so it will not be optimized out | ||
/// unless size is equal to zero.. | ||
/// unless size is equal to zero. | ||
pub fn volatile_copy_memory<T>(dst: *mut T, src: *const T, count: usize); | ||
/// Equivalent to the appropriate `llvm.memset.p0i8.*` intrinsic, with a | ||
/// size of `count` * `size_of::<T>()` and an alignment of | ||
|
Uh oh!
There was an error while loading. Please reload this page.