Unsafe Rust is an extension of the safe subset of Rust that allows performing operations that the compiler cannot verify for correctness of ownership, lifetimes, and aliasing. The main use cases include interaction with low-level libraries, FFI, manual memory control, and implementing abstractions that do not fit the safe Rust model.
Key features of unsafe:
unsafe { ... } or function: unsafe fn some_func()Example:
let x: i32 = 10; let ptr: *const i32 = &x as *const i32; unsafe { println!("Value: {}", *ptr); // dereferencing raw pointer }
Is the code inside the unsafe block completely unsafe and unchecked by the compiler, or does the compiler still apply borrow checker rules and other checks?
Answer: No, within an unsafe block, the compiler continues to check many Rust rules (such as typing, ownership rules, syntax), but allows performing only actions that would otherwise be disallowed. You cannot fully disable the borrow checker!
Example:
let mut x = 0; let r1 = &mut x as *mut i32; // Forbidden: let r2 = &mut x as *mut i32; // even inside unsafe, there will be errors if mutability is violated
Story
In an asynchronous file library, a raw pointer was used to control the buffer, but proper tracking of the buffer's lifetime was forgotten. As a result, when the file was closed, the pointer became "dangling," and access led to undefined behavior (the unsafe section did not save from use-after-free).
Story
In a custom implementation of a Vec-like structure, the programmer manually expanded the buffer via unsafe. An offset error led to incorrect copying of elements and data corruption, as alignment and layout of types were not considered.
Story
A static mutable pointer (static mut) was used in a thread descriptor without proper synchronization. As a result, a data race occurred in multi-threaded mode, leading to sporadic application crashes that were only caught during fuzzing.