【问题标题】:"closure may outlive the current function" while used as a parameter用作参数时,“闭包可能比当前函数寿命更长”
【发布时间】:2020-04-20 20:00:32
【问题描述】:

我正在尝试将函数作为参数传递并在线程内调用它。这是我要运行的代码:

use std::thread;

pub struct Image {
    pub data: Vec<u8>,
}

pub trait ImageHandler {
    fn get_image(&self) -> Option<Image>;
}

pub struct Window {
    pub id: usize,
}

impl ImageHandler for Window {
    fn get_image(&self) -> Option<Image> {
        None
    }
}

fn test(func: impl Fn() -> Option<Image> + Sync + Send + 'static) -> thread::JoinHandle<()> {
    thread::spawn(move || {
        let _image = func().unwrap();
    })
}

fn main() {
    let window = Window { id: 0 };
    test(&|| window.get_image());
}

我收到以下错误:

error[E0373]: closure may outlive the current function, but it borrows `window`, which is owned by the current function
  --> src/main.rs:30:11
   |
30 |     test(&|| window.get_image());
   |           ^^ ------ `window` is borrowed here
   |           |
   |           may outlive borrowed value `window`
   |
note: function requires argument type to outlive `'static`
  --> src/main.rs:30:5
   |
30 |     test(&|| window.get_image());
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `window` (and any other referenced variables), use the `move` keyword
   |
30 |     test(&move || window.get_image());
   |           ^^^^^^^

error[E0716]: temporary value dropped while borrowed
  --> src/main.rs:30:11
   |
30 |     test(&|| window.get_image());
   |     ------^^^^^^^^^^^^^^^^^^^^^-- temporary value is freed at the end of this statement
   |     |     |
   |     |     creates a temporary which is freed while still in use
   |     argument requires that borrow lasts for `'static`

我想Fn 应该是静态的以将其发送到线程,但是当我将其生命周期更改为'static 时,它会抱怨。 另外我不知道是否可以使用ImageHandler 作为参数。我想不通。

【问题讨论】:

  • 我不知道 rust,但看起来“借用”是 rust 术语,用于创建对其他地方“拥有”的变量的引用——在这种情况下,它是变量window,由您的main() 函数拥有。我猜想当main() 返回时该变量将不复存在,但是您传递的闭包“借用”它到一个新线程中,该线程将在main() 返回之后继续存在。这意味着线程将引用一个不存在的变量。这在任何编程语言中都是一件坏事。 Phimuemue 的回答显示了如何“移动”该值。

标签: multithreading rust


【解决方案1】:

如果闭包可以比当前线程存活,它应该拥有它需要的变量的所有权:

fn main() {
    let window = Window { id: 0 };
    test(move || window.get_image());
}

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=9cbf953b79e80e280156688d083f94fb 有操场。

但是,(我猜)这只是一个玩具示例,此修复可能适用于您的实际用例,也可能不适用于您的实际用例。如果它变得更复杂,您可以尝试让编译器相信您知道闭包不会超过当前线程(可能使用辅助 crate)或诉诸其他技术。

【讨论】:

    猜你喜欢
    • 2020-07-15
    • 2019-07-02
    • 1970-01-01
    • 2022-01-14
    • 2019-11-13
    • 2018-07-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多