如何使变量借用为 'static?

7
在中,要创建一个,需要给它一些数据,函数要求的数据具有<‘static>寿命。我有一些在运行时创建的<&[u8]>数组数据,我想将它传递给该函数。然而,它会显示以下错误信息:
argument requires that `data` is borrowed for `'static`

那么我应该如何使数据的生命周期变为 'static 呢?

4个回答

6
如果您确实需要在运行时创建数据,并且这些数据确实需要在'static生命周期中存在,那么可以使用其中一种内存泄漏的方法,例如Box::leakVec::leak,以故意泄漏堆分配的内容并确保其永远不会被释放。
虽然泄漏内存通常是要避免的,但在这种情况下,实际上是一个明智的选择。如果数据必须永久存在,则泄漏它实际上是正确的语义操作。您不希望内存被释放,永远不会被释放,这正是内存泄漏发生的情况。
示例:
fn require_static_data(data: &'static [u8]) {
    unimplemented!()
}

fn main() {
    let data = vec![1, 2, 3, 4];
    require_static_data(data.leak());
}

Playground

尽管如此,请认真思考我所提到的 really。确保你理解为什么你调用的代码需要 'static 数据,并问问自己为什么你的数据不是已经 'static 的。

  • 是否可以在编译时创建数据?Rust具有强大的构建时宏系统。例如,可以使用include_bytes!读取文件并在嵌入到可执行文件之前对其进行一些处理。

  • 是否有其他API可以使用,是否有另一个函数调用你没有看到,不需要 'static

(这些问题不是专门针对你的,而是针对将来遇到这个Q&A的任何人。)


你至少应该得到+1的赞,因为include_bytes!在编译时读取文件/数据非常神奇。我可以看出它有多么有用,但也可以看出一些我认识的开发人员会滥用它。有时候,我承认我可能会成为这两种类型的开发人员! - Kevin Anderson

5

您应该使用 CpuAccessibleBuffer::from_iter,它可以实现相同的功能,但不需要集合实现 Copy'static

let data: &[u8] = todo!();

let _ = CpuAccessibleBuffer::from_iter(
    device,
    usage,
    host_cached,
    data.iter().copied(), // <--- pass like so
);

或者如果你实际上拥有一个 Vec<u8>,你可以直接传递它:

let data: Vec<u8> = todo!();

let _ = CpuAccessibleBuffer::from_iter(
    device,
    usage,
    host_cached,
    data, // <--- pass like so
);

1
如果数据是在运行时创建的,它就没有静态生存期。 静态意味着数据在整个程序的生命周期中存在,这在某些情况下是必要的,尤其是涉及线程时。 使数据成为静态的一种方法是,就像Paul已经回答的那样,明确地声明它为静态,即:
```rust static DATA: i32 = 42; ```
static constant_value: i32 = 0;

然而,并没有一种普适的方式可以使任意数据静态化。这种推断是由借用检查器在编译时完成的,而不是由程序员完成的。
通常情况下,如果一个函数需要“static”(类型)参数(就像在这个案例中),这意味着任何不够安全的东西都可能是不安全的,你需要重新组织程序中数据的流动方式,以提供这种类型的数据的安全性。不幸的是,在这个问题的范围内,SO无法提供这种帮助。

-3
创建一个具有静态生命周期的常量:static
static NUM: i32 = 18;

1
请参考@CtrlAltF2的回答,他在您发帖后不久发布了该回答,这是我们在Stack Overflow上期望看到的答案详细程度。 - Jeremy Caney

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接