Unsafe

—— unsafe

欢马劈雪     最近更新时间:2020-08-04 05:37:59

143

Rust的内存安全依赖于强大的类型系统和编译时检测,不过它并不能适应所有的场景。 首先,所有的编程语言都需要跟外部的“不安全”接口打交道,调用外部库等,在“安全”的Rust下是无法实现的; 其次,“安全”的Rust无法高效表示复杂的数据结构,特别是数据结构内部有各种指针互相引用的时候;再次, 事实上还存在着一些操作,这些操作是安全的,但不能通过编译器的验证。

因此在安全的Rust背后,还需要unsafe的支持。

unsafe块能允许程序员做的额外事情有:

  • 解引用一个裸指针*const T*mut T
let x = 5;
let raw = &x as *const i32;
let points_at = unsafe { *raw };
println!("raw points at {}", points_at);
  • 读写一个可变的静态变量static mut
static mut N: i32 = 5;
unsafe {
    N += 1;
    println!("N: {}", N);
}
  • 调用一个不安全函数
unsafe fn foo() {
    //实现
}
fn main() {
    unsafe {
        foo();
    }
}

使用unsafe

unsafe fn不安全函数标示如果调用它可能会违反Rust的内存安全语意:

unsafe fn danger_will_robinson() {
    // 实现
}

unsafe block不安全块可以在其中调用不安全的代码:

unsafe {
    // 实现
}

unsafe trait不安全trait及它们的实现,所有实现它们的具体类型有可能是不安全的:

unsafe trait Scary { }
unsafe impl Scary for i32 {}

safe != no bug

对于Rust来说禁止你做任何不安全的事是它的本职,不过有些是编写代码时的bug,它们并不属于“内存安全”的范畴:

  • 死锁
  • 内存或其他资源溢出
  • 退出未调用析构函数
  • 整型溢出

使用unsafe时需要注意一些特殊情形:

展开阅读全文