提问人:Question Asker 提问时间:6/29/2023 最后编辑:Question Asker 更新时间:6/29/2023 访问量:1186
为什么我会收到“借用的数据在方法之外逃逸”错误?
Why do I get a "borrowed data escapes outside of method" error?
问:
我有一个变量,我必须在事件循环中编辑它。问题是我在结构函数中不断收到相同的事件循环错误。如何在仍然能够调整 over runtime 的值的情况下解决此问题?我看到的所有解决方案都导致某种形式的副本被传递,这不是我需要的。感谢您的帮助!renderer
borrowed data escapes outside of method
run
App
renderer
完全错误:
error[E0521]: borrowed data escapes outside of method
--> src/app.rs:54:9
|
50 | pub fn run(mut self, renderer: &mut Renderer) -> Result<(), pixels::Error> {
| -------- - let's call the lifetime of this reference `'1`
| |
| `renderer` is a reference that is only valid in the method body
...
54 | / self.event_loop.run(move |event, _, control_flow| {
55 | | if let Event::RedrawRequested(_) = event {
56 | |
57 | | let current_frame_time = Instant::now();
... |
84 | | }
85 | | });
| | ^
| | |
| |__________`renderer` escapes the method body here
| argument requires that `'1` must outlive `'static`
对于完整的长代码,这是我的 GitHub 存储库:https://github.com/KGL8/RayTracingPaper/tree/working_snapshot
我 App.rs 的缩短版本:
pub struct App {
// ***
}
impl App {
pub fn new() -> Result<Self, pixels::Error> {
// ***
}
pub fn create_window(event_loop: &EventLoop<()>) -> Window {
// ***
}
pub fn run(mut self, renderer: &mut Renderer) -> Result<(), pixels::Error> {
let mut previous_frame_time = Instant::now();
self.event_loop.run(move |event, _, control_flow| {
if let Event::RedrawRequested(_) = event {
let current_frame_time = Instant::now();
let timestep = current_frame_time.duration_since(previous_frame_time).as_secs_f32();
previous_frame_time = current_frame_time;
renderer.on_update(timestep, &self.input);
if let Err(err) = renderer.render(&mut self.pixels) {
log_error("renderer.draw_frame", err);
*control_flow = ControlFlow::Exit;
return;
}
}
// ***
self.window.request_redraw();
}
});
}
}
答:
您将 ,这是一个可变的引用,传递到 ,这是具有生命周期的闭包。renderer
event_loop.run
'static
pub fn run<F>(self, event_handler: F) -> !
where
F: 'static + FnMut(Event<'_, T>, [ ... ] ),
该部分的意思是“这个参数是一个具有静态生存期的闭包”。稍微分解一下:'static + FnMut
- 闭包很像函数,但它与调用函数所需的所有其他变量“捆绑在一起”
'static
是一个特殊的生命周期限制,它告诉 Rust 我们的闭包不会借用任何非生命周期的数据'static
由于事件循环想要无限期地调用,因此只要程序在运行,就必须继续存在。
您正确地使用了闭包,这会导致闭包中引用的所有变量被捕获并移动到闭包中(这就是上面的“捆绑”)。 是有问题的,因为它是一个引用,所以我们不能把它移到闭包中。event_handler
event_handler
move
renderer
我们有一个闭包,它必须一直存在到程序结束,但包括一个引用,一旦程序结束就会消失!这就是编译器所说的含义。borrowed data escapes outside of method
为了解决这个问题,我们需要向编译器承诺渲染器
会一直存在,直到程序退出。最简单的方法就是做它,
在'static
App::run()
pub fn run(mut self, renderer: &'static mut Renderer)
然后,当您实例化时,请使用lazy_static:Renderer
lazy_static! {
static ref RENDERER: Renderer = Renderer::new();
}
评论
’static
does not mean that the data lives for the duration of the program. That’s a common misconception that you can find here. It means that the data doesn’t borrow anything that does not have a lifetime.'static
评论
event_loop.run
renderer
event_loop.run
renderer
let mut renderer = Renderer::new(window, camera);
=>app.run(&mut renderer)?;