Skip to content

Commit ef37cfd

Browse files
brsonalexcrichton
authored andcommitted
std: Add more docs for ptr mod
1 parent c3ea3e4 commit ef37cfd

File tree

1 file changed

+182
-53
lines changed

1 file changed

+182
-53
lines changed

src/libstd/ptr.rs

Lines changed: 182 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,87 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//! Unsafe pointer utility functions
11+
//! Conveniences for working with unsafe pointers, the `*T`, and `*mut T` types.
12+
//!
13+
//! Working with unsafe pointers in Rust is fairly uncommon,
14+
//! and often limited to some narrow use cases: holding
15+
//! an unsafe pointer when safe pointers are unsuitable;
16+
//! checking for null; and converting back to safe pointers.
17+
//! As a result, there is not yet an abundance of library code
18+
//! for working with unsafe poniters, and in particular,
19+
//! since pointer math is fairly uncommon in Rust, it is not
20+
//! all that convenient.
21+
//!
22+
//! Use the [`null` function](fn.null.html) to create null pointers,
23+
//! the [`is_null`](trait.RawPtr.html#tymethod.is_null)
24+
//! and [`is_not_null`](trait.RawPtr.html#method.is_not_null)
25+
//! methods of the [`RawPtr` trait](trait.RawPtr.html) to check for null.
26+
//! The `RawPtr` trait is imported by the prelude, so `is_null` etc.
27+
//! work everywhere.
28+
//!
29+
//! # Common ways to create unsafe pointers
30+
//!
31+
//! ## 1. Coerce a reference (`&T`) or mutable reference (`&mut T`).
32+
//!
33+
//! ```
34+
//! let my_num: int = 10;
35+
//! let my_num_ptr: *int = &my_num;
36+
//! let mut my_speed: int = 88;
37+
//! let my_speed_ptr: *mut int = &mut my_speed;
38+
//! ```
39+
//!
40+
//! This does not take ownership of the original allocation
41+
//! and requires no resource management later,
42+
//! but you must not use the pointer after its lifetime.
43+
//!
44+
//! ## 2. Transmute an owned box (`~T`).
45+
//!
46+
//! The `transmute` function takes, by value, whatever it's given
47+
//! and returns it as whatever type is requested, as long as the
48+
//! types are the same size. Because `~T` and `*T` have the same
49+
//! representation they can be trivially,
50+
//! though unsafely, transformed from one type to the other.
51+
//!
52+
//! ```
53+
//! use std::cast;
54+
//!
55+
//! unsafe {
56+
//! let my_num: ~int = ~10;
57+
//! let my_num: *int = cast::transmute(my_num);
58+
//! let my_speed: ~int = ~88;
59+
//! let my_speed: *mut int = cast::transmute(my_speed);
60+
//!
61+
//! // By taking ownership of the original `~T` though
62+
//! // we are obligated to transmute it back later to be destroyed.
63+
//! drop(cast::transmute::<_, ~int>(my_speed));
64+
//! drop(cast::transmute::<_, ~int>(my_num));
65+
//! }
66+
//! ```
67+
//!
68+
//! Note that here the call to `drop` is for clarity - it indicates
69+
//! that we are done with the given value and it should be destroyed.
70+
//!
71+
//! ## 3. Get it from C.
72+
//!
73+
//! ```
74+
//! extern crate libc;
75+
//!
76+
//! use std::mem;
77+
//!
78+
//! fn main() {
79+
//! unsafe {
80+
//! let my_num: *mut int = libc::malloc(mem::size_of::<int>() as libc::size_t) as *mut int;
81+
//! if my_num.is_null() {
82+
//! fail!("failed to allocate memory");
83+
//! }
84+
//! libc::free(my_num as *mut libc::c_void);
85+
//! }
86+
//! }
87+
//! ```
88+
//!
89+
//! Usually you wouldn't literally use `malloc` and `free` from Rust,
90+
//! but C APIs hand out a lot of pointers generally, so are a common source
91+
//! of unsafe pointers in Rust.
1292
1393
use cast;
1494
use clone::Clone;
@@ -51,59 +131,119 @@ pub unsafe fn position<T>(buf: *T, f: |&T| -> bool) -> uint {
51131
}
52132
}
53133

54-
/// Create an unsafe null pointer
134+
/// Create an null pointer.
135+
///
136+
/// # Example
137+
///
138+
/// ```
139+
/// use std::ptr;
140+
///
141+
/// let p: *int = ptr::null();
142+
/// assert!(p.is_null());
143+
/// ```
55144
#[inline]
56145
pub fn null<T>() -> *T { 0 as *T }
57146

58-
/// Create an unsafe mutable null pointer
147+
/// Create an unsafe mutable null pointer.
148+
///
149+
/// # Example
150+
///
151+
/// ```
152+
/// use std::ptr;
153+
///
154+
/// let p: *mut int = ptr::mut_null();
155+
/// assert!(p.is_null());
156+
/// ```
59157
#[inline]
60158
pub fn mut_null<T>() -> *mut T { 0 as *mut T }
61159

62-
/**
63-
* Copies data from one location to another.
64-
*
65-
* Copies `count` elements (not bytes) from `src` to `dst`. The source
66-
* and destination may overlap.
67-
*/
160+
/// Copies data from one location to another.
161+
///
162+
/// Copies `count` elements (not bytes) from `src` to `dst`. The source
163+
/// and destination may overlap.
164+
///
165+
/// `copy_memory` is semantically equivalent to C's `memmove`.
166+
///
167+
/// # Example
168+
///
169+
/// Efficiently create a Rust vector from an unsafe buffer:
170+
///
171+
/// ```
172+
/// use std::ptr;
173+
/// use std::slice;
174+
///
175+
/// unsafe fn from_buf_raw<T>(ptr: *T, elts: uint) -> ~[T] {
176+
/// let mut dst = slice::with_capacity(elts);
177+
/// dst.set_len(elts);
178+
/// ptr::copy_memory(dst.as_mut_ptr(), ptr, elts);
179+
/// dst
180+
/// }
181+
/// ```
182+
///
68183
#[inline]
69184
pub unsafe fn copy_memory<T>(dst: *mut T, src: *T, count: uint) {
70185
intrinsics::copy_memory(dst, src, count)
71186
}
72187

73-
/**
74-
* Copies data from one location to another.
75-
*
76-
* Copies `count` elements (not bytes) from `src` to `dst`. The source
77-
* and destination may *not* overlap.
78-
*/
188+
/// Copies data from one location to another.
189+
///
190+
/// Copies `count` elements (not bytes) from `src` to `dst`. The source
191+
/// and destination may *not* overlap.
192+
///
193+
/// `copy_nonoverlapping_memory` is semantically equivalent to C's `memcpy`.
194+
///
195+
/// # Example
196+
///
197+
/// A safe swap function:
198+
///
199+
/// ```
200+
/// use std::cast;
201+
/// use std::mem;
202+
/// use std::ptr;
203+
///
204+
/// fn swap<T>(x: &mut T, y: &mut T) {
205+
/// unsafe {
206+
/// // Give ourselves some scratch space to work with
207+
/// let mut t: T = mem::uninit();
208+
///
209+
/// // Perform the swap, `&mut` pointers never alias
210+
/// ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
211+
/// ptr::copy_nonoverlapping_memory(x, &*y, 1);
212+
/// ptr::copy_nonoverlapping_memory(y, &t, 1);
213+
///
214+
/// // y and t now point to the same thing, but we need to completely forget `tmp`
215+
/// // because it's no longer relevant.
216+
/// cast::forget(t);
217+
/// }
218+
/// }
219+
/// ```
220+
///
221+
/// # Safety Note
222+
///
223+
/// If the source and destination overlap then the behavior of this
224+
/// function is undefined.
79225
#[inline]
80226
pub unsafe fn copy_nonoverlapping_memory<T>(dst: *mut T,
81227
src: *T,
82228
count: uint) {
83229
intrinsics::copy_nonoverlapping_memory(dst, src, count)
84230
}
85231

86-
/**
87-
* Invokes memset on the specified pointer, setting `count * size_of::<T>()`
88-
* bytes of memory starting at `dst` to `c`.
89-
*/
232+
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
233+
/// bytes of memory starting at `dst` to `c`.
90234
#[inline]
91235
pub unsafe fn set_memory<T>(dst: *mut T, c: u8, count: uint) {
92236
intrinsics::set_memory(dst, c, count)
93237
}
94238

95-
/**
96-
* Zeroes out `count * size_of::<T>` bytes of memory at `dst`
97-
*/
239+
/// Zeroes out `count * size_of::<T>` bytes of memory at `dst`
98240
#[inline]
99241
pub unsafe fn zero_memory<T>(dst: *mut T, count: uint) {
100242
set_memory(dst, 0, count);
101243
}
102244

103-
/**
104-
* Swap the values at two mutable locations of the same type, without
105-
* deinitialising either. They may overlap.
106-
*/
245+
/// Swap the values at two mutable locations of the same type, without
246+
/// deinitialising either. They may overlap.
107247
#[inline]
108248
pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
109249
// Give ourselves some scratch space to work with
@@ -120,30 +260,24 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
120260
cast::forget(tmp);
121261
}
122262

123-
/**
124-
* Replace the value at a mutable location with a new one, returning the old
125-
* value, without deinitialising either.
126-
*/
263+
/// Replace the value at a mutable location with a new one, returning the old
264+
/// value, without deinitialising either.
127265
#[inline]
128266
pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
129267
mem::swap(cast::transmute(dest), &mut src); // cannot overlap
130268
src
131269
}
132270

133-
/**
134-
* Reads the value from `*src` and returns it.
135-
*/
271+
/// Reads the value from `*src` and returns it.
136272
#[inline(always)]
137273
pub unsafe fn read<T>(src: *T) -> T {
138274
let mut tmp: T = mem::uninit();
139275
copy_nonoverlapping_memory(&mut tmp, src, 1);
140276
tmp
141277
}
142278

143-
/**
144-
* Reads the value from `*src` and nulls it out.
145-
* This currently prevents destructors from executing.
146-
*/
279+
/// Reads the value from `*src` and nulls it out.
280+
/// This currently prevents destructors from executing.
147281
#[inline(always)]
148282
pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
149283
// Copy the data out from `dest`:
@@ -155,13 +289,9 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
155289
tmp
156290
}
157291

158-
/**
159-
Given a **T (pointer to an array of pointers),
160-
iterate through each *T, up to the provided `len`,
161-
passing to the provided callback function
162-
163-
SAFETY NOTE: Pointer-arithmetic. Dragons be here.
164-
*/
292+
/// Given a **T (pointer to an array of pointers),
293+
/// iterate through each *T, up to the provided `len`,
294+
/// passing to the provided callback function
165295
pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
166296
if arr.is_null() {
167297
fail!("ptr::array_each_with_len failure: arr input is null pointer");
@@ -173,15 +303,14 @@ pub unsafe fn array_each_with_len<T>(arr: **T, len: uint, cb: |*T|) {
173303
}
174304
}
175305

176-
/**
177-
Given a null-pointer-terminated **T (pointer to
178-
an array of pointers), iterate through each *T,
179-
passing to the provided callback function
180-
181-
SAFETY NOTE: This will only work with a null-terminated
182-
pointer array. Barely less-dodgy Pointer Arithmetic.
183-
Dragons be here.
184-
*/
306+
/// Given a null-pointer-terminated **T (pointer to
307+
/// an array of pointers), iterate through each *T,
308+
/// passing to the provided callback function
309+
///
310+
/// # Safety Note
311+
///
312+
/// This will only work with a null-terminated
313+
/// pointer array.
185314
pub unsafe fn array_each<T>(arr: **T, cb: |*T|) {
186315
if arr.is_null() {
187316
fail!("ptr::array_each_with_len failure: arr input is null pointer");

0 commit comments

Comments
 (0)