unsafe fn
- Rust course
- Advanced
- Lesson 32/81
- 4 min
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.
Practice 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.
Starter code
fn main() {
// buraya yaz
}Sample 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]));
}Expected output
7 10
Questions and answers
Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.
1 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 Correct answer
- Always
- Never
Explanation: 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.
2 Unchecked access
t += unsafe { *v.____(i) };
t += unsafe { *v.get_unchecked(i) };
Explanation: get_unchecked does no bounds check; the contract is on the caller.
3 Item and meaning
| Term | Meaning |
|---|---|
unsafe fn |
Function with a contract |
# Safety |
Contract documentation |
// SAFETY: |
Where the contract is met |
Safe wrapper |
Hides the unsafe |