//! Unsafe Example //! //! In Rust, unsafe means less automated safety, not no safety. It's an //! escape hatch for code not normally allowed by the Rust compiler. //! //! Unsafe code allows the following 4 abilities: //! //! 1. Dereferencing raw pointers //! 2. Calling an unsafe function or method //! 3. Acessing/Mutating a mutable static variable (global) //! 4. Implementing an unsafe trait use std::slice; extern "C" { fn abs(input: i32) -> i32; } // Immutable static variable (global) - safe static HELLO_WORLD: &str = "Hello, world!"; // Mutable static variable - unsafe to access or mutate static mut COUNTER: u32 = 0; fn raw_pointer() { let mut num = 5; // Casting references to raw pointers // Raw pointers can be created in safe code, // but can only be dereferenced in unsafe code let r1 = &num as *const i32; let r2 = &mut num as *mut i32; unsafe { println!("r1 is: {}", *r1); println!("r2 is: {}", *r2); } } /// An unsafe function can only be called within an unsafe block /// This is essentially the same as wrapping the entire function in an unsafe block, /// as an unsafe block in the function body is redundant unsafe fn dangerous() {} /// A 'safe' function can wrap unsafe code fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { let len = slice.len(); let ptr = slice.as_mut_ptr(); // Get the raw pointer of the slice assert!(mid <= len); unsafe { // These slice methods are unsafe because they require a valid pointer. // Since the Rust compiler can not verify the safety of the pointers, // the calls must be in an unsafe block. The function is still considered // safe, though, because the original pointer is valid, and the bounds // of the slice are verified with the assert call. ( slice::from_raw_parts_mut(ptr, mid), slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid) ) } } /// A call to a function from a foreign programming language is considered /// unsafe, as rust can not verify the safety of the external code. /// While this can be wrapped in a 'safe' function, it is (unfortunately) up to the programmer /// to make sure the call is actually safe fn c_library_call() { unsafe { println!("Absolute value of -3 according to C: {}", abs(-3)); } } /// Mutable static variables (globals) are unsafe to access /// or mutate due to the possibility of data races in multithreaded code fn add_to_count(inc: u32) { unsafe { COUNTER += inc; // Mutating a mutable static variable is unsafe } } fn main() { raw_pointer(); add_to_count(3); unsafe { dangerous(); println!("COUNTER: {}", COUNTER); // Accessing a mutable static variable is unsafe } c_library_call(); }