capypad
0 day streak
rust / intermediate
Snippet

Unsafe Raw Pointers and MaybeUninit

Unsafe Rust grants direct memory access beyond what safe Rust permits. Raw pointers (*const T, *mut T) can be dereferenced only in unsafe blocks, acknowledging undefined behavior risks. MaybeUninit<T> is essential for representing potentially uninitialized memory—it does not run T's destructor or assume a valid value. This pattern is crucial for FFI boundaries, custom allocators, and performance-critical code that must avoid zero-initialization overhead. Always ensure proper initialization before reading MaybeUninit data.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
use std::mem::MaybeUninit;
use std::ptr;
 
fn demo_raw_pointer() {
let mut value: i32 = 42;
let ptr = &mut value as *mut i32;
unsafe {
println!("Original: {}", *ptr);
*ptr = 100;
println!("Modified: {}", *ptr);
}
}
 
fn demo_maybe_uninit() {
const SIZE: usize = 5;
let mut buffer = [MaybeUninit::<u64>::uninit(); SIZE];
for i in 0..SIZE {
buffer[i] = MaybeUninit::new((i as u64) * 10);
}
let values = unsafe { ptr::read(buffer.as_ptr() as *const [u64; SIZE]) };
println!("Buffer: {:?}", values);
}
 
fn main() {
demo_raw_pointer();
demo_maybe_uninit();
}
Breakdown
1
let ptr = &mut value as *mut i32
Create raw mutable pointer—no lifetime attached, just memory address
2
unsafe { *ptr = 100; }
Unsafe block acknowledges dereferencing raw pointer is callers responsibility
3
let mut buffer = [MaybeUninit::<u64>::uninit(); SIZE]
MaybeUninit array—values are uninitialized, no Drop called