【问题标题】:Trying to return reference from RwLock, "borrowed value does not live long enough" Error试图从 RwLock 返回引用,“借来的值不够长”错误
【发布时间】:2017-03-11 00:38:50
【问题描述】:

我最近一直在做我的第一个 Rust 项目,但遇到了障碍。我正在使用 HashMap 映射 Strings 到 AtomicUsize 整数。 HashMapRwLock 保护以允许并发访问。我希望能够在HashMap 中返回对AtomicUsize 值的引用,但是如果我尝试在RwLockWriteGuard 的生命周期之后将这些引用返回给调用者,我会收到borrowed value does not live long enough 的错误。我在下面复制了一个最小的示例,并将相同的示例放在 Rust 游乐场here

use std::collections::HashMap;
use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, Ordering};

struct Bar {
    val: AtomicUsize
}

impl Bar {
    pub fn new() -> Self {
        Bar { val: AtomicUsize::new(0) }
    }
}

struct Foo {
    map: RwLock<HashMap<String, Bar>>
}


impl Foo {
    pub fn get(&self, key: String) -> &Bar {
        self.map.write().unwrap().entry(key).or_insert(Bar::new())
    }
}

fn main() {
    let foo = Foo {map: RwLock::new(HashMap::new())};
    let bar = foo.get("key".to_string());
}

我得到的错误发生在线路上:

self.map.write().unwrap().entry(key).or_insert(Bar::new())

而且是因为借来的价值的寿命不够长。我已经阅读了一些讨论此错误的其他帖子,尤其是 one 尤其相关。读完之后,我可以收集到从互斥锁返回的值的生命周期必须小于互斥锁的生命周期,这似乎完全排除了我正在尝试做的事情。我明白为什么这是不可能的,因为如果我们有一个指向 Hashmap 的指针,而另一个将值插入到互斥体中导致它被调整大小,那么我们将有一个悬空指针。

那么,我的问题是双重的。首先,我只是好奇我是否正确理解了这个问题,或者是否还有其他原因导致我被禁止做我想做的事情?我的第二个问题是,如果没有Box 原子整数并将它们存储在HashMap 中,是否还有另一种方法可以完成我想要做的事情?这种方法似乎对我有用,因为我们可以返回指向始终有效的 Boxed 值的指针。然而,这种方法似乎效率低下,因为它需要额外的指针间接层和额外的分配。谢谢!

【问题讨论】:

  • 除了调整地图大小之外,其他人还可以简单地删除您引用的条目。
  • 你说得对!对于我的用例,我不需要删除密钥,但编译器当然不知道。

标签: hashmap rust borrow-checker rwlock


【解决方案1】:

您是正确的,您不能返回对超过 MutexGuard 的内容的引用,因为这可能会导致指针悬空。

不过,将内容包装在 Box 中并没有帮助! Box 是一个拥有的指针,除了重定向之外,就引用生命周期而言,它的行为类似于包含的值。毕竟,如果您返回了对它的引用,其他人可能会将其从 HashMap 中删除并取消分配。

根据你想对参考做什么,我可以想到几个选项:

  1. 不是Boxing 这些值,而是将它们包装在Arc 中。从HashMap 获取时,您将克隆Arc,并且可以同时存在多个引用。

  2. 您也可以将MutexGuard 连同参考一起返回;请参阅this question,如果您只想对值进行操作然后相对较快地删除引用,这将很有效。这将保持互斥锁直到你完成它。

【讨论】:

  • 感谢您的反馈,这非常有帮助!我想我将采用使用Arc 的方法开始,因为我希望能够创建对可以远远超过MutexGuard 的值的多个引用。对于我的用例,一旦插入 HashMap 中的任何值,我就不需要删除它们,所以我想知道 Arc 是否可能比我需要的更重。我想知道是否有办法存储指向 HashMap 中值的指针,然后使用生命周期告诉编译器只要 HashMap 在范围内,引用就有效。似乎更适合我!
  • 今天早上我做了更多的工作,并提出了一个使用Shared 指针而不是Arcdifferent solution。它需要unsafe 代码和夜间 Rust,但我认为它仍然很有趣。我还没有运行任何基准测试,但我认为应该快一点。
猜你喜欢
  • 1970-01-01
  • 2016-09-20
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
  • 2014-12-26
  • 1970-01-01
  • 2020-07-23
  • 1970-01-01
相关资源
最近更新 更多