我试图用从文件中获取的一些数据填充缓冲区,然后从该缓冲区读取以对该数据进行处理。所有这些都在循环内迭代进行。
如果我这样做,它将完美编译:
use std::fs::File;
use std::io::{BufReader, IoSliceMut, Read};
fn do_something(buffer_0: &[u8; 8], buffer_1: &[u8; 2]) {
// Do something
}
fn main() {
let file = File::open("/path/to/file").expect("Error opening file");
let mut reader = BufReader::new(file);
let buffer_0 = &mut [0; 8];
let buffer_1 = &mut [0; 2];
loop {
let buffer = &mut [IoSliceMut::new(buffer_0), IoSliceMut::new(buffer_1)];
reader
.read_vectored(buffer)
.expect("Error reading from file");
do_something(buffer_0, buffer_1);
}
}
现在,如果我在循环外部声明buffer
,如下所示:
use std::fs::File;
use std::io::{BufReader, IoSliceMut, Read};
fn do_something(buffer_0: &[u8; 8], buffer_1: &[u8; 2]) {
// Do something
}
fn main() {
let file = File::open("/path/to/file").expect("Error opening file");
let mut reader = BufReader::new(file);
let buffer_0 = &mut [0; 8];
let buffer_1 = &mut [0; 2];
let buffer = &mut [IoSliceMut::new(buffer_0), IoSliceMut::new(buffer_1)];
loop {
reader
.read_vectored(buffer)
.expect("Error reading from file");
do_something(buffer_0, buffer_1);
}
}
出现以下编译错误:
error[E0502]: cannot borrow `*buffer_0` as immutable because it is also borrowed as mutable
--> src/main.rs:21:22
|
15 | let buffer = &mut [IoSliceMut::new(buffer_0), IoSliceMut::new(buffer_1)];
| -------- mutable borrow occurs here
...
19 | .read_vectored(buffer)
| ------ mutable borrow later used here
20 | .expect("Error reading from file");
21 | do_something(buffer_0, buffer_1);
| ^^^^^^^^ immutable borrow occurs here
buffer_1
当然也是这样。
我不明白为什么这段代码在循环内被认为是不安全的。另外,是否可以在不移动buffer
声明的情况下使其安全?
非常感谢锈大师的智慧:)
答案 0 :(得分:1)
在第一个示例中,buffer
的每个实例仅持续循环一次。由于存在非词性生存期,因此编译器可以计算出在调用IoSliceMut
之后,您不会重用read_vectored
的那些实例,因此释放了它们持有的可变借项,并且代码进行了编译
在第二个示例中,您明确地说IoSliceMut
的这两个实例应在整个循环中保留,并且应将它们用于对{{1 }}-因此,直到最后一次迭代,它们的可变借位才可能释放。