在链表节点之间复制数据

Copying data between linked list nodes

我正在编写一个虚拟机,目前正在处理使用链表实现的内存。我已经实现了 malloc,它将一个新节点添加到列表中,free 标记了一个节点将被 malloc 重用,现在我正在研究 realloc。我遇到的问题是,由于存在两个可变引用,我无法在链表的两个节点之间复制数据,这是一个最小示例:

use std::collections::LinkedList;

struct MemoryBlock {
    address: u64,
    size: u64,
    data: Vec<u8>
}

struct Memory {
    blocks: LinkedList<MemoryBlock>,
}

impl Memory {
    fn malloc(&mut self, alloc_size: u64) -> u64 {
        self.blocks.push_back(MemoryBlock {
            address: 1,
            size: alloc_size,
            data: vec![0x00]
        });
        
        1
    }

    fn realloc(&mut self, address: u64, new_size: u64) -> u64 {
        let new_address = self.malloc(new_size);
        
        let mut old_block = self.blocks.iter_mut().find(|b| b.address == address).unwrap();
        let mut new_block = self.blocks.iter_mut().find(|b| b.address == new_address).unwrap();
        
        new_block.data[0] = old_block.data[0];
        
        new_address
    }
}

fn main() {
    let mut memory = Memory {
        blocks: LinkedList::new()
    };
    
    memory.blocks.push_back(MemoryBlock {
        address: 0,
        size: 1,
        data: vec![0x00]
    });
    
    memory.realloc(0, 2);
}

我曾尝试使 'old_block' 不可变,但我不能同时借入一个可变借用和一个不可变借用。有什么方法可以以不同的方式构造我的代码或使用任何其他方法(不安全的除外)来使其正常工作?我知道我可以使用向量,然后使用切片作为 'hack' 来完成它,但如果可能的话我更愿意使用链表。

您可以重组代码,让 Rust 编译器知道 old_blocknew_block 指向不同的位置。这也会更有效,因为 LinkedList 只遍历一次。

fn realloc(&mut self, address: u64, new_size: u64) -> u64 {
    let new_address = self.malloc(new_size);

    let mut old_block = None;
    let mut new_block = None;

    for block in &mut self.blocks {
        if block.address == address {
            old_block = Some(block);
        } else if block.address == new_address {
            new_block = Some(block);
        }
    }

    new_block.unwrap().data[0] = old_block.unwrap().data[0];

    new_address
}

Playground