Expand description
Raw, unsafe pointers, *const T
, and *mut T
.
Working with raw pointers in Rust is uncommon, typically limited to a few patterns. Raw pointers
can be out-of-bounds, unaligned, or null
. However, when loading from or storing to a raw
pointer, it must be valid for the given access and aligned. When using a field expression,
tuple index expression, or array/slice index expression on a raw pointer, it follows the rules
of in-bounds pointer arithmetic.
Storing through a raw pointer using *ptr = data
calls drop
on the old value, so
write
must be used if the type has drop glue and memory is not already
initialized - otherwise drop
would be called on the uninitialized memory.
Use the null
and null_mut
functions to create null pointers, and the
is_null
method of the *const T
and *mut T
types to check for null.
The *const T
and *mut T
types also define the offset
method, for
pointer math.
§Common ways to create raw pointers
§1. Coerce a reference (&T
) or mutable reference (&mut T
).
let my_num: i32 = 10;
let my_num_ptr: *const i32 = &my_num;
let mut my_speed: i32 = 88;
let my_speed_ptr: *mut i32 = &mut my_speed;
To get a pointer to a boxed value, dereference the box:
let my_num: Box<i32> = Box::new(10);
let my_num_ptr: *const i32 = &*my_num;
let mut my_speed: Box<i32> = Box::new(88);
let my_speed_ptr: *mut i32 = &mut *my_speed;
This does not take ownership of the original allocation and requires no resource management later, but you must not use the pointer after its lifetime.
§2. Consume a box (Box<T>
).
The into_raw
function consumes a box and returns
the raw pointer. It doesn’t destroy T
or deallocate any memory.
let my_speed: Box<i32> = Box::new(88);
let my_speed: *mut i32 = Box::into_raw(my_speed);
// By taking ownership of the original `Box<T>` though
// we are obligated to put it together later to be destroyed.
unsafe {
drop(Box::from_raw(my_speed));
}
Note that here the call to drop
is for clarity - it indicates
that we are done with the given value and it should be destroyed.
§3. Create it using &raw
Instead of coercing a reference to a raw pointer, you can use the raw borrow
operators &raw const
(for *const T
) and &raw mut
(for *mut T
).
These operators allow you to create raw pointers to fields to which you cannot
create a reference (without causing undefined behavior), such as an
unaligned field. This might be necessary if packed structs or uninitialized
memory is involved.
#[derive(Debug, Default, Copy, Clone)]
#[repr(C, packed)]
struct S {
aligned: u8,
unaligned: u32,
}
let s = S::default();
let p = &raw const s.unaligned; // not allowed with coercion
§4. Get it from C.
#[allow(unused_extern_crates)]
extern crate libc;
unsafe {
let my_num: *mut i32 = libc::malloc(size_of::<i32>()) as *mut i32;
if my_num.is_null() {
panic!("failed to allocate memory");
}
libc::free(my_num as *mut core::ffi::c_void);
}
Usually you wouldn’t literally use malloc
and free
from Rust,
but C APIs hand out a lot of pointers generally, so are a common source
of raw pointers in Rust.