【问题标题】:error: xxx does not live long enough错误:xxx 的寿命不够长
【发布时间】:2016-07-02 18:10:50
【问题描述】:

这行得通:

fn user_add<'x>(data: &'x Input, db: &'x mut Database<'x>) -> HandlerOutput {
    //let input: UserAddIn = json::decode(&data.post).unwrap();
    //let username = input.username.as_bytes();
    //let password = input.password.as_bytes();
    db.put(b"Hi", b"hello");
    //db.delete(username);
    Ok("Hi".to_string())
}

这不起作用:

fn user_add<'x>(data: &'x Input, db: &'x mut Database<'x>) -> HandlerOutput {
    //let input: UserAddIn = json::decode(&data.post).unwrap();
    //let username = input.username.as_bytes();
    //let password = input.password.as_bytes();
    let my_str = "hi".to_string();
    let username = my_str.as_bytes();
    db.put(username, b"hello");
    //db.delete(username);
    Ok("Hi".to_string())
}

编译器输出:

src/handlers.rs:85:17: 85:23 error: `my_str` does not live long enough
src/handlers.rs:85      let username = my_str.as_bytes();
                                       ^~~~~~
src/handlers.rs:80:77: 89:2 note: reference must be valid for the lifetime 'x as defined on the block at 80:76...
src/handlers.rs:80 fn user_add<'x>(data: &'x Input, db: &'x mut Database<'x>) -> HandlerOutput {
src/handlers.rs:81      //let input: UserAddIn = json::decode(&data.post).unwrap();
src/handlers.rs:82      //let username = input.username.as_bytes();
src/handlers.rs:83      //let password = input.password.as_bytes();
src/handlers.rs:84      let my_str = "hi".to_string();
src/handlers.rs:85      let username = my_str.as_bytes();
                   ...
src/handlers.rs:84:32: 89:2 note: ...but borrowed value is only valid for the block suffix following statement 0 at 84:31
src/handlers.rs:84      let my_str = "hi".to_string();
src/handlers.rs:85      let username = my_str.as_bytes();
src/handlers.rs:86      db.put(username, b"hello");
src/handlers.rs:87      //db.delete(username);
src/handlers.rs:88      Ok("Hi".to_string())
src/handlers.rs:89 }

我看过几个关于 Rust 生命周期的问题,我认为这本书并没有那么清楚地说明它。我仍然使用生命周期作为试验和错误。这种特殊情况让我感到困惑,因为我已经多次尝试与编译器作斗争,而这只是我得到的最后一个错误。如果你有一些 Rust 技能,请考虑编辑书中关于生命周期的部分。

【问题讨论】:

    标签: rust


    【解决方案1】:

    在第一种情况下,b"Hi" 是一个字节文字,类型为&amp;'static [u8],意思是“u8 的切片具有无限的生命周期”。函数put 需要一些生命周期'x,因为'static live 比任何生命周期都大,Rust 很乐意使用它。

    第二种情况

    let my_str = "hi".to_string();
    let username = my_str.as_bytes();
    

    username 是对my_str 内部缓冲区的引用,不能超过它。编译器抱怨是因为put 的第一个参数应该有一个生命周期'x,它比my_str 的生命周期更宽(局部于user_add)。 Rust 不允许你这样做,因为 db 会在函数调用结束时指向悬空数据:

    user_add(input, &mut db);
    // `my_str` was local to `user_add` and doesn't exist anymore
    // if Rust had allowed you to put it in `db`, `db` would now contain some invalid data here
    

    【讨论】:

      【解决方案2】:

      感谢 @mcarton 回答错误发生的原因。在这个答案中,我希望也清楚如何解决它。


      编译器的代码生成是完美的但是错误信息是 只是让我非常困惑。

      问题出在我创建的另一个库中,恰好是 数据库。数据库结构包含一个包含切片的条目。 切片的生命周期设置为:

      struct Entry<'a> {
          key: &'a [u8],
          value: &'a [u8],
      }
      
      pub struct Database<'a> {
          file: File,
          entries: Vec<Entry<'a>>,
      }
      

      这意味着切片保存的数据需要比 数据库结构。 username 变量超出范围,但持有对它的引用的数据库仍然存在。所以这意味着数据库必须保存比它更长的数据,比如静态变量,这使得数据库毫无用处。

      库编译好了。但错误显示在其他地方。

      解决方案是将切片交换为向量,因为 向量不是指针。向量的寿命可能比数据库少。

      struct Entry {
          key: Vec<u8>,
          value: Vec<u8>,
      }
      
      pub struct Database {
          file: File,
          entries: Vec<Entry>,
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-05-26
        • 1970-01-01
        • 2020-12-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-02-28
        • 1970-01-01
        相关资源
        最近更新 更多