延长“for"变量的寿命 [英] Prolonging a 'for' variable's life

查看:52
本文介绍了延长“for"变量的寿命的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我在 Rust 0.12.0 中编译以下代码时,出现以下错误:

when I compile the below code in Rust 0.12.0, I get the following error:

error: borrowed value does not live long enough
let _ = match re.captures(a_line.unwrap().as_slice()) {

如何延长 a_line 的生命周期,以便将 c1 推送到 vect1 上?

How do I prolong a_line's lifetime so that c1 can be pushed onto vect1?

let vect = process_file(filename_ref);
...
fn process_file(filename: &str) -> Vec<&str> {

    let re = regex!(r"^(\w+)\t(\w+)\t(\w+)\t(\w+)\n$");
    let mut vect1 = Vec::new();

    let filepath = Path::new(filename);
    let _ = match File::open(&filepath) {
        Ok(f) => {
            let mut filebuffer = BufferedReader::new(f);
            for a_line in filebuffer.lines() {
                let _ = match re.captures(a_line.unwrap().as_slice()) {
                    Some(c) =>  {
                        let c1 = c.at(1);
                        vect1.push(c1);
                        ...
                    },
                   ...
               };
           } // end for
       },
       Err(e) => println!("Error: {}", e)
   };

   return vect1;

}

推荐答案

简短的回答是,不,您不能像这样延长"变量的生命周期.

The short answer is, no, you can't just 'extend' the lifetime of a variable like this.

这是一个连接类型的游戏:

This is a game of connect the types:

  • .lines 返回一个 Lines 实例,它是一个 Iterator>.
  • a_line 是一个 IoResult= 结果,等等.unwrap 返回一个 String
  • .as_slice 给出字符串数据的非拥有视图,通过引用上的 'a 生命周期,静态限制为仅在 String 存在避免了 C++ 中的悬空引用和 use-after-free 问题(有关 String&str 的更多信息:这个答案 & 字符串指南).
  • .captures 接受一个具有生命周期的 &str('t)并尝试返回一个 Captures 持续那么长时间.在这种情况下,&str 的生命周期是 a_line 之外的 String 的生命周期,所以 c 是一个 Captures 存储只有这么长时间有效的数据.
  • .at 返回一个 &str't 数据的生命周期,Captures 正在存储,即返回的 &str 只能保证与输入 captures 的原始 &str 一样长(不能超过原始 String 存在,因为它管理内存中的文本)
  • .lines returns a Lines instance, which is an Iterator<IoResult<String>>.
  • a_line is an IoResult<String> = Result<String, IoError>, and so .unwrap returns a String
  • .as_slice gives a non-owning view of the string's data which is, via the 'a lifetime on the references, statically restricted to only be usable while the String exists avoiding the problem of dangling references and use-after-free in C++ (for more about String vs. &str: this answer & the strings guide).
  • .captures takes a &str with some lifetime (the 't) and tries to return a Captures that lasts that long. In this case, the lifetime of the &str is the lifetime of the String out of a_line, and so c is a Captures storing data that is only valid this long.
  • .at returns a &str with the 't lifetime of the data that the Captures is storing, that is, the returned &str is only guaranteed to last as long as the original &str fed into captures (which can't be longer than how long the original String exists, since that's managing the text in memory)

因此,c1 的持续时间仅与 a_line 中的 String 一样长,并且 String 是有作用域的在循环内部,也就是说,每次遍历循环时,都会得到一个新的 String,它在最后被释放.如果编译器通过允许将其放置在 vect1 中而让它逃脱,则代码将容易出现使用后释放/悬空引用内存安全错误,因为 String 每个&str 指向在每次迭代结束时被释放(例如 vect1 中的所有 &strreturnvect1 行将指向垃圾).

Hence, c1 only lasts for as long as the String from a_line, and that String is scoped inside the loop, that is, each time you step through the loop, you get a new String which is deallocated at the end. If the compiler let it escape by allowing it to be placed in vect1, the code would be prone to use-after-free/dangling reference memory safety bugs as the String each &str points into is freed at the end of each iteration (e.g. all the &strs in vect1 on the return vect1 line would be pointing to garbage).

要解决这个问题,您需要切断内存依赖:当前 &str 无法控制自己的内存,因此依赖于父"Strings 被正确放置.相反,您可以通过使向量内容成为完全成熟的 Strings,例如,让矢量内容控制自己的命运(好吧,记忆).vect1.push(c1.to_string()).这将使 vect1 成为 Vec,然后这些值和循环内的 a_line 值之间不再有联系.然后可以随意释放/修改/修改该变量,而不会影响 vect1 的内容.

To fix this, you need to cut the memory dependency: currently the &strs are not in control of their own memory, and thus are dependent on the "parent" Strings being placed correctly. Instead, you could give the vector contents control of its own destiny (well, memory), by making them fully-fledged Strings, e.g. vect1.push(c1.to_string()). This will make vect1 a Vec<String>, and then there is no longer a connection between those values and the a_line value inside the loop. That variable can then be freed/mangled/munged as much as it likes without affecting the contents of vect1.

这篇关于延长“for"变量的寿命的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆