【问题标题】:Rust referencing data owned by the current function error for VecRust 引用 Vec 的当前函数错误所拥有的数据
【发布时间】:2021-02-08 10:59:20
【问题描述】:

我正在编写代码来解析 CLI 参数,但遇到了一个非常常见的 Rust 错误。

什么更改(理想情况下不需要将所有内容分配给单个 let 变量,我需要进行哪些更改来修复编译错误?

我一直在查看很多类似的帖子,并重新阅读了 rust book 中关于所有权的章节。但是我还没有找到针对我的具体情况的解决方案。

我解析args的代码如下:

The full file on github is here:

pub fn new<'a>(
        args: env::Args,
        default_world_def: Config<'static>,
        presets: Vec<&'static str>,
    ) -> Result<Config<'a>, String> {

        let args2 = args;
        let args_vec = args2.collect::<Vec<String>>();
        let args_slice = args_vec.as_slice();

        let result = match args_slice {
            [_, preset] => {
                if preset == "help" {
                    Err(format!(
                        "try: gol
try: gol {:?}
try: gol [width height num_starting_cells seed display_dead display_alive] (e.g: gol 40 40 40 4045)",
                        presets
                    ))
                } else if presets.contains(&&preset[..]) {
                    Ok(Config::Preset {
                        key: preset.to_string(),
                    })
                } else {
                    Err(format!("Unknown preset, choose from {:?}.", presets))
                }
            }
            [_] => Ok(default_world_def),
            [_, w, h, n, s] => {
                let (width, height, num_starting_cells, seed) = Config::parse_args(&w, &h, &n, &s)?;

                Ok(Config::WorldDef {
                    width,
                    height,
                    num_starting_cells,
                    seed,
                    dead_char: None,
                    alive_char: None,
                })
            }
            [_, w, h, n, s, d, a] => {
                let (width, height, num_starting_cells, seed) = Config::parse_args(&w, &h, &n, &s)?;

                Ok(Config::WorldDef {
                    width,
                    height,
                    num_starting_cells,
                    seed,
                    dead_char: Some(&d),
                    alive_char: Some(&a),
                })
            }
            args => Err(format!(
                "Expected at least 4 or 6 args but got {}",
                args.len() - 1
            ))
        };

        result

这会导致错误:

error[E0515]: cannot return value referencing local variable `args_vec`
  --> src/config.rs:77:9
   |
27 |         let args_slice = args_vec.as_slice();
   |                          -------- `args_vec` is borrowed here
...
77 |         result
   |         ^^^^^^ returns a value referencing data owned by the current function

我试过了:

  • 修改生命周期参数(做更多事情static
  • 将每个方法调用的结果分配给一个变量(参见上面的args2args_vecargs_slice
  • 使args: env::Args 函数的参数new 成为引用(&amp;)

据我了解,问题是 result 引用了一个/所有 args 变量,这些变量超出范围并在 new 方法的末尾被删除,@987654335 @未来依赖。

【问题讨论】:

  • 会的!我还将发布一个完整文件的 github 链接。

标签: rust


【解决方案1】:

match 给出Ok(Config::WorldDef { ... dead_char: Some(&amp;d), alive_char: Some(&amp;a), } 时,最后两个引用是来自Strings 的切片,由args_vec 拥有 (通过args_slice访问)。

当函数退出时,args_vec 不再存在,因此如果 Rust 没有抱怨,结果中的引用将悬空。

我建议您在dead_charalive_char 成员中存储Strings 而不是&amp;str;这样,结果可以将这些所有权归属于来自args_vec 的字符串。 顺便说一句,如果你这样做,我不确定args_slice 是否有用;我认为您可以在match 语句中使用args_vec,因为它不会在之后使用。

【讨论】:

  • 谢谢。这是有道理的。我没有考虑如何访问match 中的数据。我正在更新我的代码,并且能够在此过程中删除许多生命周期参数。编译完所有内容后将标记为答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-08-15
  • 2020-05-24
相关资源
最近更新 更多