Rust:借用检查同步和异步代码之间的差异?

问题描述 投票:0回答:0

提前道歉,但这让我抓狂。每次我认为我理解了 Rust 的借用检查器时,我都会遇到这样的事情,这让我的大脑崩溃了:-(提前感谢你帮助我重新振作起来。

我正在使用包装 libpcap 的第三方库(https://github.com/rust-pcap/pcap),其 Capture::next_packet() [1] 调用将“&mut self”作为参数,并且返回一个“数据包”。如果在具有同步功能的循环中(

sync_no_problem()
,见下文),我存储这个数据包,借用检查器工作正常。但是,如果我采用 完全相同的代码 并在异步函数中运行它(
async_has_borrow_problem()
,如下),借用检查器会抱怨我无法重新借用与 &mut 相同的函数。具体错误:

error[E0499]: cannot borrow `cap` as mutable more than once at a time
   --> src/main.rs:249:19
    |
249 |         let pkt = cap.next_packet().unwrap();
    |                   ^^^^^^^^^^^^^^^^^ `cap` was mutably borrowed here in the previous iteration of the loop
250 |         let owned_pkt = pkt.clone();
251 |         captured.insert(1, owned_pkt);
    |         ----------------------------- first borrow used here, in later iteration of loop

如果我让一个异步函数(下面的“nested_async_no_proble()”)调用同步函数,真的很麻烦,借用检查器就可以了。有人可以向我解释这里发生了什么吗?

仅供参考:我试图简化示例以删除 pcap 引用,但我无法重现该问题,因此我认为这与它们的工作方式有关。我还在 Packet 结构上尝试了丰富的 .clone() 和 .to_owned() 认为可以解决问题但它没有:-(

提前谢谢你。

[1] 捕获::下一个数据包():https://github.com/rust-pcap/pcap/blob/main/src/lib.rs#L1238 [2] 数据包:https://github.com/rust-pcap/pcap/blob/main/src/lib.rs#L654

use pcap::Capture;

fn sync_no_problem() {
    let captured = std::collections::HashMap::new();
    let cap = pcap::Device::lookup().unwrap().unwrap().open().unwrap();
    for i in 0..5 {
        let pkt = cap.next_packet().unwrap();
        captured.insert(1, pkt);
    }
    println!("{:?}", captured);
}

async fn async_has_borrowing_problem() {
    let mut captured = std::collections::HashMap::new();
    let mut cap = pcap::Device::lookup().unwrap().unwrap().open().unwrap();
    for i in 0..5 {
        let pkt = cap.next_packet().unwrap();
        let owned_pkt = pkt.clone();
        captured.insert(1, owned_pkt);
    }
    println!("{:?}", captured);
}

async fn nested_async_no_problem() {
    // this has no problems!!?
    sync_no_problem();
}

#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
    sync_no_problem();
    // calling this has problems
    // async_has_borrowing_problem().await;
    nested_async_no_problem().await;
}
rust pcap rust-tokio
© www.soinside.com 2019 - 2024. All rights reserved.