MST

星途 面试题库

面试题:Rust中所有权原则如何保障内存安全

请阐述Rust所有权原则的主要内容,并举例说明它是怎样在实际代码中防止内存泄漏和悬空指针问题的。
40.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

Rust所有权原则主要内容

  1. 所有权的定义:每个值在Rust中都有一个变量,称为该值的所有者。当所有者离开其作用域时,这个值将被丢弃。
  2. 唯一性:在任何时刻,一个值只能有一个所有者。这确保了对内存的独占访问,避免数据竞争。
  3. 借用:可以在不转移所有权的情况下使用值,即借用。借用分为可变借用(&mut)和不可变借用(&)。不可变借用可以有多个,但可变借用同一时间只能有一个,这保证了在修改数据时没有其他引用在使用它。
  4. 生命周期:每个引用都有一个生命周期,它表示引用保持有效的作用域。生命周期规则确保引用不会指向无效的数据。

防止内存泄漏和悬空指针示例

fn main() {
    // 定义一个字符串变量s,s是该字符串的所有者
    let s = String::from("hello"); 

    // 将s的所有权转移给s2,此时s不再是所有者,不能再使用s
    let s2 = s; 

    // 这里如果使用s会报错,因为s的所有权已经转移
    // println!("{}", s); 

    // 函数调用,将s2的所有权转移到函数中
    take_ownership(s2); 

    // 这里如果使用s2会报错,因为所有权已经转移到take_ownership函数
    // println!("{}", s2); 
}

fn take_ownership(some_string: String) {
    // some_string在函数结束时离开作用域,字符串占用的内存被释放
    println!("{}", some_string); 
}

// 借用示例
fn borrow_string(some_string: &String) {
    println!("{}", some_string); 
}

fn main() {
    let s = String::from("world");
    // 借用s,不会转移所有权
    borrow_string(&s); 
    // 这里仍然可以使用s,因为所有权没有转移
    println!("{}", s); 
}

在上述代码中,take_ownership 函数通过获取字符串的所有权,在函数结束时字符串被自动释放,防止了内存泄漏。在借用示例中,borrow_string 函数通过借用字符串,在函数结束后字符串的所有者(s)仍可正常使用,并且借用规则保证了在借用期间不会出现悬空指针,因为如果在借用期间所有者被释放,编译器会报错。