在容器之后创建借用值时,如何添加对容器的引用?

moa*_*lon 10 rust borrow-checker

由于与代码组织相关的原因,我需要编译器接受以下(简化)代码:

fn f() {
    let mut vec = Vec::new();
    let a = 0;
    vec.push(&a);
    let b = 0;
    vec.push(&b);
    // Use `vec`
}
Run Code Online (Sandbox Code Playgroud)

编译器抱怨

error: `a` does not live long enough
 --> src/main.rs:8:1
  |
4 |     vec.push(&a);
  |               - borrow occurs here
...
8 | }
  | ^ `a` dropped here while still borrowed
  |
  = note: values in a scope are dropped in the opposite order they are created

error: `b` does not live long enough
 --> src/main.rs:8:1
  |
6 |     vec.push(&b);
  |               - borrow occurs here
7 |     // Use `vec`
8 | }
  | ^ `b` dropped here while still borrowed
  |
  = note: values in a scope are dropped in the opposite order they are created
Run Code Online (Sandbox Code Playgroud)

但是,我很难说服编译器在它引用的变量之前删除向量.vec.clear()不起作用,也不起作用drop(vec).mem::transmute()不工作或者(强制vec'static).

我发现的唯一解决方案是将参考文献转换为&'static _.还有其他方法吗?甚至可以在安全的Rust中编译它吗?

She*_*ter 13

甚至可以在安全的Rust中编译它吗?

不.在一般情况下,您要做的事情本质上不安全的.

该集合包含对在删除集合本身之前将被删除的变量的引用.这意味着集合的析构函数可以访问不再有效的引用.析构函数可以选择取消引用其中一个值,从而破坏Rust的内存安全保障.

注意:范围中的值将按照创建它们的相反顺序删除

正如编译器告诉您的那样,您需要重新排序代码.您实际上没有说出 "与代码组织相关的原因" 的限制是什么,但直接修复是:

fn f() {
    let a = 0;
    let b = 0;
    let mut vec = Vec::new();
    vec.push(&a);
    vec.push(&b);
}
Run Code Online (Sandbox Code Playgroud)

一个不太明显的是:

fn f() {
    let a;
    let b;

    let mut vec = Vec::new();
    a = 0;
    vec.push(&a);
    b = 0;
    vec.push(&b);
}
Run Code Online (Sandbox Code Playgroud)

总而言之,一旦启用了非词汇生命周期,您的原始代码就会起作用!借用检查器变得更加细化了价值需要多长时间.

等等 ; 我只是说集合可能会访问无效内存,如果其中的值在集合之前被删除,现在编译器允许这种情况发生?是什么赋予了?

这是因为标准库给我们带来了一个偷偷摸摸的伎俩.集合喜欢VecHashSet保证它们不会在析构函数中访问它们的泛型参数.他们使用不稳定的#[may_dangle]功能将其传达给编译器.

也可以看看:


归档时间:

查看次数:

308 次

最近记录:

7 年,1 月 前