在链接列表节点之间复制数据

发布于 2025-01-22 19:58:36 字数 1420 浏览 6 评论 0原文

我正在编写一台虚拟机,目前正在使用链接列表来实现其内存。我已经实施了Malloc,该Malloc在列表中添加了一个新节点,该节点是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”不可分割,但后来我无法有一个可变的和一个不可变的可变的同时借。是否有任何方法可以以不同的方式构造我的代码或任何其他方法(不安全除外)可以使其正常工作?我知道我可以使用矢量,然后将切片用作“黑客”来完成它,但是如果可能的话,我更喜欢使用链接列表。

I'm writing a virtual machine and currently working on its memory which is implemented using a linked list. I have implemented malloc which adds a new node to the list, free which marks a node to be reused by malloc and now I am working on realloc. The problem i have is that I cannot copy data between two nodes of the linked list due to there being two mutable references, here is a minimum example:

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);
}

I have tried to make 'old_block' immutable but then I cannot have one mutable and one immutable borrow at the same time. Is there any way to structure my code differently or any other method (other than unsafe) to get it to work? I know I can use a vector and then use slices as a 'hack' to get it done but I would prefer to use a linked list if possible.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

芸娘子的小脾气 2025-01-29 19:58:36

您可以重组代码,以便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
}

You can restructure the code so that the Rust compiler knows that old_block and new_block point to different locations. This will also be more efficient as the LinkedList is only traversed once.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文