|
| 1 | +//use core::slice; |
| 2 | +use std::slice; |
| 3 | + |
| 4 | + |
| 5 | +unsafe fn dangerous() { |
| 6 | + println!("Danger!"); |
| 7 | +} |
| 8 | + |
| 9 | +fn split_at_mut(values: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]){ |
| 10 | + let len = values.len(); |
| 11 | + let ptr = values.as_mut_ptr(); |
| 12 | + |
| 13 | + assert!(mid<=len); |
| 14 | + unsafe { |
| 15 | + ( |
| 16 | + slice::from_raw_parts_mut(ptr, mid), |
| 17 | + slice::from_raw_parts_mut(ptr.add(mid), len-mid), |
| 18 | + ) |
| 19 | + } |
| 20 | + //(&mut values[..mid], &mut values[mid..]) |
| 21 | +} |
| 22 | + |
| 23 | +/* |
| 24 | +- "C" defines ABI the external function uses. |
| 25 | +- ABI defines how to call the function at the assembly level. |
| 26 | +- The "C" ABI is the most common and follows the C programming language's ABI. |
| 27 | + */ |
| 28 | +extern "C" { |
| 29 | + // names and signatures of external functions from C |
| 30 | + fn abs(input: i32) -> i32; |
| 31 | +} |
| 32 | + |
| 33 | + |
| 34 | +#[no_mangle] |
| 35 | +pub extern "C" fn call_from_c() { |
| 36 | + println!("Output from a Rust function! Callable by C."); |
| 37 | +} |
| 38 | + |
| 39 | +// immutable global static variable |
| 40 | +static HELLO_WORLD: &str = "Hello world!"; |
| 41 | + |
| 42 | +// mutable global static variable |
| 43 | +static mut COUNTER: u32 = 0; |
| 44 | +fn add_to_count(inc: u32) { |
| 45 | + // mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior |
| 46 | + // so must be within unsafe block. |
| 47 | + unsafe { |
| 48 | + COUNTER += inc; |
| 49 | + } |
| 50 | +} |
| 51 | + |
| 52 | +//unsafe traits |
| 53 | +unsafe trait Foo { |
| 54 | + // methods |
| 55 | +} |
| 56 | + |
| 57 | +unsafe impl Foo for i32 { |
| 58 | + // |
| 59 | +} |
| 60 | + |
| 61 | +fn main() { |
| 62 | + println!("1) Dereference two raw pointers that point to the same data, output after changing value for one of them."); |
| 63 | + let mut num = 5; |
| 64 | + |
| 65 | + let r1 = &num as *const i32; |
| 66 | + let r2 = &mut num as *mut i32; |
| 67 | + |
| 68 | + // a random address in memory |
| 69 | + let address = 0x012345usize; |
| 70 | + let r = address as *mut i32; |
| 71 | + |
| 72 | + unsafe { |
| 73 | + //can change r2 but not r1 because r1 is const raw pointer. |
| 74 | + *r2 += 1; |
| 75 | + println!("r1 is: {}", *r1); |
| 76 | + println!("r2 is: {}", *r2); |
| 77 | + // accessing this random address results in segmentation fault |
| 78 | + //println!("r is: {}", *r); |
| 79 | + } |
| 80 | + |
| 81 | + println!("2) Obtain 10K elements at address {address} results in segmentation fault"); |
| 82 | + let values= unsafe { |
| 83 | + // appending ; results in returning unit (empty structure) |
| 84 | + // removing ; will incur segmentation fault as it tries to access a random address. |
| 85 | + slice::from_raw_parts_mut(r, 10000); |
| 86 | + }; |
| 87 | + println!("10K elements (fake obtaining. true obtaining results in segmentation fault) are {:?}", values); |
| 88 | + |
| 89 | + println!("3) Call an unsafe function"); |
| 90 | + unsafe { |
| 91 | + dangerous(); |
| 92 | + } |
| 93 | + |
| 94 | + println!("4) Create a safe abstraction over unsafe code"); |
| 95 | + |
| 96 | + let mut v = vec![1,2,3,4,5,6]; |
| 97 | + let r = &mut v[..]; |
| 98 | + let (a,b) = r.split_at_mut(3); |
| 99 | + |
| 100 | + println!("First 3 elements are {:?}", a); |
| 101 | + println!("Elements after first 3 elements are {:?}", b); |
| 102 | + assert_eq!(a, &mut [1,2,3]); |
| 103 | + assert_eq!(b, &mut [4,5,6]); |
| 104 | + |
| 105 | + println!("4.1) Safely call own split_at_mut() that contains an unsafe block"); |
| 106 | + |
| 107 | + let (a,b) = split_at_mut(&mut v, 3); |
| 108 | + println!("First 3 elements are {:?}", a); |
| 109 | + println!("Elements after first 3 elements are {:?}", b); |
| 110 | + assert_eq!(a, &mut [1,2,3]); |
| 111 | + assert_eq!(b, &mut [4,5,6]); |
| 112 | + |
| 113 | + println!("5) Use extern functions to call external code"); |
| 114 | + unsafe { |
| 115 | + println!("Absolute value of -3 according to C is {}", abs(-3)); |
| 116 | + } |
| 117 | + |
| 118 | + println!("6) Accessing or changing a global or static variable"); |
| 119 | + println!("name is {}", HELLO_WORLD); |
| 120 | + |
| 121 | + unsafe { |
| 122 | + // mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior |
| 123 | + // so must be within unsafe block. |
| 124 | + println!("Counter is {COUNTER}"); |
| 125 | + } |
| 126 | + add_to_count(3); |
| 127 | + unsafe { |
| 128 | + // mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior |
| 129 | + // so must be within unsafe block. |
| 130 | + println!("Counter after adding 3 is {COUNTER}"); |
| 131 | + } |
| 132 | + |
| 133 | +} |
0 commit comments