【问题标题】:How to pass a borrowed string into a an outer scoped Vec in Rust?如何将借用的字符串传递给 Rust 中的外部范围 Vec?
【发布时间】:2022-01-01 05:16:21
【问题描述】:

我一边看书一边尝试学习生锈的手。 所以我的程序试图从 macOS 读取 SPDisplaysDataType 并且我想以某种方式构造这个命令的输出(还不知道如何实现这一点,任何想法都会受到欢迎)。

现在我似乎无法编译,因为我无法弄清楚这个借用错误。

use std::process::Command;

fn main() {
    let output = Command::new("system_profiler")
        .arg("SPDisplaysDataType")
        .output()
        .expect("Failed getting display data");

    let display_text = String::from_utf8(output.stdout)
        .expect("Cannot read string from output");    

    let mut gpus: Vec<Vec<&str>> = Vec::new();
    let mut gpu_structure: Vec<&str> = Vec::new();

    for (index, line) in display_text.lines().enumerate() {

        if line.contains("Chipset Model") {
            gpus.push(gpu_structure.clone());

            gpu_structure = Vec::new();
            let mut gpu_title_string = format!("{}", index);

            gpu_title_string.push_str(line);

            let cloned = gpu_title_string.clone();
            gpu_structure.push(cloned.as_str());
            continue;
        }
         gpu_structure.push(line);
    }
}

我得到的错误是:

   |
21 |             gpus.push(gpu_structure.clone());
   |                       ------------- borrow later used here
...
29 |             gpu_structure.push(cloned.as_str());
   |                                ^^^^^^ borrowed value does not live long enough
30 |             continue;
31 |         }
   |         - `cloned` dropped here while still borrowed

【问题讨论】:

  • cloned 是一个临时变量,所以它的借用(正如编译器所说的那样)活得不够长。如果您在循环中创建字符串,则需要将gpu_structure 设为Vec&lt;String&gt;,并使用gpu_structure.push(cloned)

标签: rust borrow-checker


【解决方案1】:

我用一个函数处理了同样的问题。该函数接受 String 然后返回为 &'static str。您可以使用 Box::leak 功能。然后您的变量将获得静态生命周期。这显然会导致内存泄漏。更多内容请阅读Box::leak from rust docs




fn string_to_static_str(s: String) -> &'static str {
    Box::leak(s.into_boxed_str())
}

//String does not live long enough. Converting to 'static str
let s: &'static str = string_to_static_str(some_string);

...


【讨论】:

  • 您的回答并不能真正解释问题。它仅提供一种解决方法,如果在不理解的情况下使用可能会有害。我相信至少提及解决方案,例如制作矢量商店String 或其他类型或解释差异会改善这个答案。
【解决方案2】:

问题看起来像您试图在内部范围中克隆一个值,并将对该新值的引用存储在外部范围中。 gpu_structure 正在存储一个 &amp;str (cloned.as_str()),但是当您退出 if 语句时,cloned 会被删除。以下是一些更改,将 &amp;str 的几个实例替换为 String 应该可以工作。

use std::process::Command;

fn main() {
    let output = Command::new("system_profiler")
        .arg("SPDisplaysDataType")
        .output()
        .expect("Failed getting display data");

    let display_text = String::from_utf8(output.stdout)
        .expect("Cannot read string from output");    

    let mut gpus: Vec<Vec<String>> = Vec::new();
    let mut gpu_structure: Vec<String> = Vec::new();

    for (index, line) in display_text.lines().enumerate() {

        if line.contains("Chipset Model") {
            gpus.push(gpu_structure.clone());

            gpu_structure = Vec::new();
            let gpu_title_string = format!("{}{}", index, line);

            gpu_structure.push(gpu_title_string.clone());
            continue;
        }
         gpu_structure.push(line.to_string());
    }
}

当使用堆分配数据结构(如Vec)和非静态字符串时,通常最好使用String,因为它们与借用检查器配合得更好,而且它们的所有权更容易处理.

【讨论】:

  • 谢谢!这使它工作,所以如果我理解正确 - 当我使用 &str 我“借用”它但变量被删除了?并且在使用 String 时,我将所有权“移至” Vec?
  • 是的,这是一个简单的修复方法,但对于大多数 borrowed value does not live long enough 错误,请牢记这一点。
猜你喜欢
  • 2018-02-10
  • 2015-03-22
  • 1970-01-01
  • 2017-08-14
  • 1970-01-01
  • 1970-01-01
  • 2022-06-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多