gpt4 book ai didi

rust - 循环中的变量生命周期不够长

转载 作者:行者123 更新时间:2023-11-29 08:14:20 30 4
gpt4 key购买 nike

这几天我一直在玩 Rust,而且我仍在为内存管理而苦苦挣扎(数字)。

我写了一个simple project通过对文本文件进行词法分析/解析来创建结构层次结构(“关键字”)。

关键字定义如下:

pub struct Keyword<'a> {
name: String,
code: u32,
parent: Option<&'a Keyword<'a>>,
}

这是我对这个 C 结构的等价物:

typedef struct Keyword Keyword;

struct Keyword {
char* name;
unsigned int code;
Keyword* parent;
};

hierarchy 只是关键字的容器,定义如下:

pub struct KeywordHierarchy<'a> {
keywords: Vec<Box<Keyword<'a>>>,
}

impl<'a> KeywordHierarchy<'a> {
fn add_keyword(&mut self, keyword: Box<Keyword<'a>>) {
self.keywords.push(keyword);
}
}

parse 函数(它是完整解析器的 stub )中,我重新创建了在我的代码中产生生命周期错误的条件。

fn parse<'a>() -> Result<KeywordHierarchy<'a>, String> {

let mut hierarchy = KeywordHierarchy { keywords: Vec::new() };

let mut first_if = true;
let mut second_if = false;

while true {

if first_if {

// All good here.

let root_keyword = Keyword {
name: String::from("ROOT"),
code: 0,
parent: None,
};
hierarchy.add_keyword(Box::new(root_keyword));

first_if = false;
second_if = true;
}

if second_if {

// Hierarchy might have expired here?

// Find parent
match hierarchy.keywords.iter().find(|p| p.code == 0) {
None => return Err(String::from("No such parent")),
Some(parent) => {

// If parent is found, create a child
let child = Keyword {
name: String::from("CHILD"),
code: 1,
parent: Some(&parent),
};
hierarchy.add_keyword(Box::new(child));
}
}

second_if = false;
}

if !first_if && !second_if {
break;
}
}

Ok(hierarchy)

}

有一个 while 循环遍历词法分析器标记。

在第一个 if 中,我将 ROOT 关键字添加到层次结构中,这是唯一没有父级的关键字,一切都按预期顺利进行.

在第二个 if 中,我解析了子关键字,并且在调用 KeywordHierarchy.add_keyword() 时出现生命周期错误。

hierarchy.keywords` does not live long enough

你们能推荐一种惯用的方法来解决这个问题吗?

干杯。

附言点击here Playground

最佳答案

我在您的设计中看到的直接问题是您的循环将修改 hierarchy.keywords 向量(在 first_if block 中),但它也从 hierarchy.keywords 向量(在 second_if block 中)借用元素。

这是有问题的,因为修改向量可能会导致其后备缓冲区被重新分配,如果允许的话,将使所有现有的向量借用无效。 (因此这是不允许的。)

您是否考虑过使用 arena 而不是 Vec 来保存关键字?竞技场的设计使您可以在其中分配新事物,同时仍然可以借用先前在竞技场内分配的元素。


更新:这是您的代码的修订版本,它说明了如何使用 arena(在本例中为 rustc_arena::TypedArena ,但这只是为了让它在 play.rust-lang.org 服务上运行)以及 Vec<&Keyword> 来处理查找。

https://play.rust-lang.org/?gist=fc6d81cb7efa7e4f32c481ab6482e587&version=nightly&backtrace=0

关键的代码是这样的:

首先:KeywordHierarchy 现在拥有一个 arena 和一个 vec:

pub struct KeywordHierarchy<'a> {
keywords: Vec<&'a Keyword<'a>>,
kw_arena: &'a TypedArena<Keyword<'a>>,
}

第二:现在添加关键字会分配竞技场中的位置,并在 vec 中存储对该位置的引用:

fn add_keyword(&mut self, keyword: Keyword<'a>) {
let kw = self.kw_arena.alloc(keyword);
self.keywords.push(kw);
}

第三:fn parse 函数现在接受一个 arena(引用)作为输入,因为我们需要 arena 比 fn parse 的堆栈帧还长:

fn parse<'a>(arena: &'a TypedArena<Keyword<'a>>) -> Result<KeywordHierarchy<'a>, String> {
...

第四:为了避免将 hierarchy 借用为可变的借用检查器问题,同时也对其进行迭代,我将 hierarchy 修改移到了 Find parent match 之外:

        // Find parent
let parent = match hierarchy.keywords.iter().find(|p| p.code == 0) {
None => return Err(String::from("No such parent")),
Some(parent) => *parent, // (this deref is important)
};
// If parent is found, create a child
let child = Keyword {
name: String::from("CHILD"),
code: 1,
parent: Some(parent),
};
hierarchy.add_keyword(child);
second_if = false;

关于rust - 循环中的变量生命周期不够长,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45055117/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com