创建实例时发生生锈"does not live long enough"错误



我在写一个玩具操作系统。我无法修复以下生命周期错误。

由于does not live long enough

,我的代码无法编译
error[E0597]: `fb_config` does not live long enough
--> src/main.rs:37:45
|
26 | pub extern "sysv64" fn kernel_main (mut fb_config: FrameBufferConfig) -> ! {
|                                     ------------- has type `FrameBufferConfig<'1>`
...
37 |     let mut pixel_writer = PixelWriter::new(&mut fb_config);
|                            -----------------^^^^^^^^^^^^^^-
|                            |                |
|                            |                borrowed value does not live long enough
|                            argument requires that `fb_config` is borrowed for `'1`
...
66 | }
| - `fb_config` dropped here while still borrowed

这是我内核代码的一部分。FrameBufferConfig具有寿命,并且是可变的,借用了PixelWriter::new()PixelWriter也有一个生命周期,它有传递的FrameBufferConfig作为成员。

// src/main.rs
pub extern "sysv64" fn kernel_main (mut fb_config: FrameBufferConfig) -> ! {
let mut pixel_writer = PixelWriter::new(&mut fb_config);
...
}
pub struct FrameBufferConfig<'a> {
pub frame_buffer: FrameBuffer<'a>,   // https://docs.rs/uefi/0.3.2/uefi/proto/console/gop/struct.FrameBuffer.html
...
}
pub struct PixelWriter<'a> {
fb_config: &'a mut FrameBufferConfig<'a>,
pixel_writer: unsafe fn(&mut FrameBuffer, usize, Rgb),
}
impl<'a> PixelWriter<'a> {
pub fn new(fb_config: &'a mut FrameBufferConfig<'a>) -> Self {
...
PixelWriter {
fb_config,
pixel_writer,
}
}

恕我直言,PixelWriter应该比FrameBufferCOnfig活得更长。它看起来fb_config(在kernel_main的参数中定义)和PixelWriter(在kernel_main中定义)都处于活动状态,直到kernel_main结束。所以我觉得fb_config活得够久了。

为了解决这个问题,我尝试了以下两种方法。
  1. 限制PixelWriter的生存期。但它失败了。我们得到相同的错误。
pub extern "sysv64" fn kernel_main (mut fb_config: FrameBufferConfig) -> ! {
{
let mut pixel_writer = PixelWriter::new(&mut fb_config);
}  // PixelWriter dropped?
...
}  // fb_config dropped?
  1. 将owner移动到本地值。它传递编译。但这是多余的。
pub extern "sysv64" fn kernel_main (mut fb_config: FrameBufferConfig) -> ! {
let mut tmp = fb_config;   // move owner here.
let mut pixel_writer = PixelWriter::new(&mut tmp);
...
}

你知道为什么会发生这个错误吗?既然我是生锈的初学者,我犯了一辈子的错误吗?谢谢你的帮助!

fb_config: &'a mut FrameBufferConfig<'a>,

你已经过度限制了这个生命周期。

  • &'a mut FrameBufferConfig表示'a指定该FrameBufferConfig被借用多长时间-FrameBufferConfig将至少被借用'a
  • FrameBufferConfig<'a>意味着'a指定了FrameBufferConfig内部引用的生命周期,因此FrameBufferConfig<'a>不能超过'a

把这两个放在一起需要编译器得出结论,在PixelWriter::new(&mut tmp)被执行后,FrameBufferConfig被借用了剩余的存在(因为如果'a结束,FrameBufferConfig<'a>就不再有效,但是FrameBufferConfig不能停止被借用,直到'a结束),因此永远不能丢弃或以任何方式使用。

一般来说,当涉及到可变引用时,您将更需要使用不同的生命周期(&'a mut Foo<'a>几乎总是无用的)。一个简单的原则(不是最优的,但是一个开始的地方)是为每个涉及的&mut使用单独的生命周期,或者为所有涉及的&mut使用单独的生命周期。(具体走哪条路取决于具体情况。)在您的示例中,我们只需要为两个角色设置两个生命周期:

pub struct PixelWriter<'fb, 'gop> {
fb_config: &'fb mut FrameBufferConfig<'gop>,
...

(为了保持一致性,我从库文档中取了生命周期名称'gop)

也有可能(取决于你的程序需要)PixelWriter应该拥有fb_config,而不是对它有一个可变的引用,即

pub struct PixelWriter<'gop> {
fb_config: FrameBufferConfig<'gop>,
...

但是这是否合适取决于你的程序需要是什么。特别是,如果你要从一个FrameBufferConfig顺序地创建多个PixelWriter,引用可能是合适的,但是如果你要为每个FrameBufferConfig只创建一个,那么所有权会简化事情。

相关内容

  • 没有找到相关文章

最新更新