MST
星途 面试题库

面试题:Rust生命周期在函数返回值涉及引用时的内存安全考量

编写一个Rust函数,该函数接收两个字符串切片作为参数,返回其中较长的那个字符串切片。要求正确处理生命周期问题,确保函数返回的引用在调用者使用时不会指向已释放的内存。解释为什么这样的生命周期处理是必要的,以及可能会出现什么错误情况。
23.1万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试
fn longer_string(s1: &str, s2: &str) -> &str {
    if s1.len() > s2.len() {
        s1
    } else {
        s2
    }
}

生命周期处理的必要性

  1. Rust的借用规则:Rust有严格的借用规则,以确保内存安全。其中一条规则是,引用的生命周期必须小于或等于被引用对象的生命周期。在这个函数中,我们返回的是传入的字符串切片之一,这意味着返回的引用的生命周期必须与传入参数的生命周期相关联。
  2. 防止悬空引用:如果不处理好生命周期,可能会出现返回的引用指向已释放的内存,即悬空引用。这会导致未定义行为,在运行时可能会引发崩溃或数据损坏。

可能出现的错误情况

  1. 错误的生命周期标注:如果尝试给函数添加错误的生命周期标注,例如:
fn longer_string<'a, 'b>(s1: &'a str, s2: &'b str) -> &'static str {
    if s1.len() > s2.len() {
        s1
    } else {
        s2
    }
}

这里错误地标注返回值的生命周期为 'static,意味着返回的引用会一直存活,而实际上它应该与传入参数的生命周期相关。编译器会报错,指出 s1s2 的生命周期与 'static 不匹配。 2. 生命周期不匹配:如果在调用函数时,传入的字符串切片的生命周期不正确,也会导致错误。例如:

fn main() {
    let result;
    {
        let s1 = "hello";
        {
            let s2 = "world";
            result = longer_string(s1, s2);
        }
        // 这里s2已经超出作用域,result如果没有正确处理生命周期,
        // 就可能指向已释放的内存,编译器会阻止这种情况发生
    }
    println!("{}", result);
}

在这个例子中,如果 longer_string 函数没有正确处理生命周期,编译器会报错,指出 result 的生命周期可能会超出 s2 的生命周期。