Rust Lang Book Ch.19 Unsafe
Unsafe
Unsafe能够绕开rust强调的内存安全保证(memory safety guarantees),Unsafe的五大功能是:
1. Dereference a raw pointer,获取一个裸指针对应的数据
2. 调用其他unsafe的代码
3. 获取或者修改可变的static变量
4. 实现unsafe的特性
5. 获取union的域
unsafe不能关闭borrow checker,只有这5个功能。
书中建议将unsafe代码用安全的API包裹起来。
Unsafe-Dereference a raw pointer
Rust中raw pointer有*const T和*mut T两种。
let mut num = 5;
let r1 = &num as *const i32;
let r2 = &mut num as *mut i32;
unsafe {
println!("r1 is: {}", *r1);
println!("r2 is: {}", *r2);
}
raw pointer与引用和smart pointer的不同之处在于:
1. 允许忽略borrowing rule,可以有多个同时写
2. 不保证指向有效的memory
3. 可能是null
4. 没有自动的内存释放和清理
let address = 0x012345usize; let r = address as *const i32;
这里使用as将引用映射为对应的raw pointer。
程序员可以在safe code中创建raw pointer,但是只被允许在unsafe code中dereference这些指针。
Unsafe-Calling an unsafe Function or Method
use std::slice; fn split_at_mut(slice: &mut [i32], mid: usize) -> (&mut [i32], &mut [i32]) { let len = slice.len(); let ptr = slice.as_mut_ptr(); assert!(mid <= len); unsafe { ( slice::from_raw_parts_mut(ptr, mid),
//slice::from_raw_parts_mut获取一个raw pointer和一个length,然后创建对应的slice slice::from_raw_parts_mut(ptr.add(mid), len - mid), ) } }
Unsafe-Call External Code
比如从c的FFI(Foreign Function Interface)中调用函数,当然,程序员要负责对应的c library正确。
extern "C" { fn abs(input: i32) -> i32; } fn main() { unsafe { println!("Absolute value of -3 according to C: {}", abs(-3)); } }
或者
这里的#[no_mangle]是告诉Rust编译器不要对这个函数名做mangling操作,即给对应的用于编译的函数名
#[no_mangle] pub extern "C" fn call_from_c() { println!("Just called a Rust function from C!"); }
Unsafe-修改静态变量
static mut COUNTER: u32 = 0; fn add_to_count(inc: u32) { unsafe { COUNTER += inc; } } fn main() { add_to_count(3); unsafe { println!("COUNTER: {}", COUNTER); } }
这里书中说明不变量和静态量的区别在于,静态量可能可以改变,此外,静态量的占空间大小是一定的,但是不变量可能会复制很多份。
Unsafe-实现Unsafe特性
unsafe trait Foo { // methods go here } unsafe impl Foo for i32 { // method implementations go here } fn main() {}