不安全的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; }
|