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() {}

 

posted @ 2020-10-28 00:09  雪溯  阅读(256)  评论(0编辑  收藏  举报