Rust
unsafe fn
Define and call unsafe fn.
unsafe fn
An unsafe fn is a function with a contract the caller must keep and the compiler can't check. The contract is written in a doc comment headed # Safety; the call site needs an unsafe block:
/// Reads the value the pointer points to.
///
/// # Safety
/// `p` must point to a valid, aligned and initialized `i32`.
unsafe fn oku(p: *const i32) -> i32 {
unsafe { *p }
}
let x = 7;
let n = unsafe { oku(&x) };
Examples in the standard library: get_unchecked, from_utf8_unchecked, slice::from_raw_parts.
A safe wrapper
Putting the unsafe call inside a safe function and keeping the contract there frees the user from unsafe:
fn toplam_hizli(v: &[i32]) -> i32 {
let mut t = 0;
for i in 0..v.len() {
// SAFETY: i < v.len() comes from the loop range.
t += unsafe { *v.get_unchecked(i) };
}
t
}
The function itself is safe: whatever slice it's called with, no undefined behaviour can occur.
Exercise Safe wrapper
Write a documented unsafe fn oku(p: *const i32) -> i32 and the safe toplam_hizli function above. Print the results of oku(&x) for let x = 7; and toplam_hizli for [1, 2, 3, 4] separated by a space.
Show example solution
/// İşaretçinin gösterdiği değeri okur.
///
/// # Safety
/// `p` geçerli, hizalı ve başlatılmış bir `i32`'ye işaret etmelidir.
unsafe fn oku(p: *const i32) -> i32 {
unsafe { *p }
}
fn toplam_hizli(v: &[i32]) -> i32 {
let mut t = 0;
for i in 0..v.len() {
// SAFETY: i < v.len() döngü aralığından gelir.
t += unsafe { *v.get_unchecked(i) };
}
t
}
fn main() {
let x = 7;
let n = unsafe { oku(&x) };
println!("{} {}", n, toplam_hizli(&[1, 2, 3, 4]));
}
Test yourself
-
When can <code>get_unchecked(i)</code> be used safely?
- Only in release
- When it's known for sure by other means that i is within bounds
- Always
- Never
Show answer
When it's known for sure by other means that i is within bounds — If the loop is over 0..v.len(), the bound is already proven; still, the compiler often removes the bounds check itself, so measure first.
-
Unchecked access
t += unsafe { *v.____(i) };
Show answer
t += unsafe { *v.get_unchecked(i) };
-
Item and meaning
- unsafe fn
- Function with a contract
- # Safety
- Contract documentation
- // SAFETY:
- Where the contract is met
- Safe wrapper
- Hides the unsafe
Next lesson: static mut