不安全的Rust
不安全的Rust拥有以下能力:
- 解引用裸指针
 
- 调用不安全的函数或者方法
 
- 访问或修改可变静态变量
 
- 实现不安全的trait
这种方法不会关闭rust中的借用检查器或者禁用任何其他的rust安全检查规则,只提供上述
几个不被编译器检查内存安全的功能,这种代码的正确与否,由程序员自己保证 
 
解用裸指针
裸指针分为两种:
- 不可变裸指针:const T(这里的是const连用的,并不是解引用的*,写法就是如此)
 
- 可变裸指针: *mut T(同上)
 
(1) 允许忽略借用规则,可以同是拥有不可变和可变的指针,或者是多个指向相同位置的
可变指针
(2) 不保证指向的内存有效
(3) 允许为空
(4) 不能实现任何自动清理的功能
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
   | fn main() {     let mut num = 5;               let r1 = &num as *const i32;      let r1 = &num as *mut i32;                                    unsafe {         println!("r1 = {}",*r1);         println!("r2 = {}",*r2);       }
      let add = 0x12345usize;      let r = add as *const i32;
    }
  | 
 
调用不安全函数或者方法
1 2 3 4 5 6 7 8 9 10 11
   | unsafe fn dangerous() {     println!("do something dangerous");   }
  fn main() {     unsafe {         dangerous();       }                     }
  | 
 
创建不安全代码的抽象(相当于封装)
1 2 3 4 5 6 7 8 9 10 11 12 13
   | fn foo () {     let mut num = 5;     let r1 =&num as *const i32;     let r2 =&num as *mut i32;
      unsafe {         println!("* r1 = {}",r1);         println!("* r2 = {}",r2);       }   } fn main() {     foo();   }
  | 
 
调用C语言的函数
1 2 3 4 5 6 7 8
   | extern "C" {     fn abs(input: i32) -> i32;   } fn main() {     unsafe {         println!("abs(-3): {}",abs(-3));       }   }
  | 
 
C语言调用Rust
1 2 3 4 5
   | mkdir learn cd learn cargo new foo --lib cd foo vim src/lib.rs
   | 
 
1 2 3 4 5
   | #![crate_type = "staticlib"] #[no_mangle]  pub extern fn foo () {     println!("use rust");   }
   | 
 
1 2 3 4
   | [dependencies] [lib] name = "foo" crate-type = ["staticlib"]
   | 
 
1 2 3 4
   | cd /learn cd target ls cp libfoo.a /learn 
   | 
 
这个时候你就可以看到libfoo.a文件
之后使用:
1 2 3 4 5
   | extern void foo(); int main() {     foo();     return 0;   }
   | 
 
1 2
   | gcc -o main main.c libfoo.a -lpthread -ldl  ./main
   | 
 
访问或者修改可变静态变量
静态变量中的值有一个固定的内存地址(使用值总会访问相同的地址),而常量则允许任何在
被用到的时候复制数据
静态变量可以是可变的,虽然可能不安全(使用unsafe包含)
 
1 2 3 4 5
   | static HELLO_WORLD: &str = "Hello World";
  fn main() {     println!("{}",HELLO_WORLD);   }
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14
   | static mut COUNTER: u32 = 0; fn add_counter(inc: u32) {     unsafe {         COUNTER += inc;       }   } fn main() {     add_counter(3);     add_counter(3);     unsafe {                println!("counter: {}",COUNTER);       }   }
   | 
 
实现不安全的trait
- 当至少一个方法中包含编译器不能验证的变量时,该trait就是不安全的
 
- 在trait之前增加unsafe声明它是不安全的,同时trait也必须使用unsafe标记
 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
   | unsafe trait Foo {     fn foo(&self);   }
  struct Bar();
  unsafe impl Foo for Bar {     fn foo(&self) {         println!("foo");       }   }
  fn main() {     let a = Bar();     a.foo;   }
  |