diff --git a/.idea/misc.xml b/.idea/misc.xml index 3583a37..5fa0a85 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -36,6 +36,7 @@ + diff --git a/.idea/rust.iml b/.idea/rust.iml index 1263a66..08adc04 100644 --- a/.idea/rust.iml +++ b/.idea/rust.iml @@ -145,6 +145,10 @@ + + + + @@ -179,6 +183,7 @@ + diff --git a/.idea/workspace.xml b/.idea/workspace.xml index 450794f..29a8446 100644 --- a/.idea/workspace.xml +++ b/.idea/workspace.xml @@ -2,6 +2,8 @@ + + @@ -15,10 +17,10 @@ - + - - + + @@ -52,7 +54,6 @@ @@ -112,11 +114,11 @@ false false - - - + - + @@ -281,11 +283,11 @@ + - @@ -322,11 +324,11 @@ - + - - + + @@ -334,7 +336,7 @@ - + @@ -356,13 +358,6 @@ - - - - - - - @@ -789,8 +784,15 @@ - - + + + + + + + + + diff --git a/unsafe_blocks/Cargo.toml b/unsafe_blocks/Cargo.toml new file mode 100644 index 0000000..4c6d43e --- /dev/null +++ b/unsafe_blocks/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "unsafe_blocks" +version = "0.1.0" +authors = ["Timothy Warren "] +edition = "2018" + +[dependencies] diff --git a/unsafe_blocks/src/main.rs b/unsafe_blocks/src/main.rs new file mode 100644 index 0000000..4227373 --- /dev/null +++ b/unsafe_blocks/src/main.rs @@ -0,0 +1,95 @@ +//! 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(); +}