如何管理内存以插入和删除内容?

时间:2013-07-26 14:15:58

标签: c memory memory-management operating-system

为方便起见,我只使用纯文本示例。例如,对于句子I have a cat,我需要malloc 13个char个变量的插槽,以便它存储所有带有最终\0的字母。

但是,如果现在我想在lovely之前插入cat怎么办?似乎我必须创建一个足够大的新数组并将所有内容复制过来。

更糟糕的是,因为计算机无法预测会添加多少东西,所以每次添加新字母时我都必须重新执行此操作并复制一些东西,即完成所有操作每个字母l o v e l y,这不是一个聪明的解决方案。 (计算机提前不知道'可爱'这个词,呃?)

“更好”的解决方案似乎是在第一个位置创建一个足够大的数组,这样每次插入一个新的字母时,程序只会复制并移回它后面的所有内容。但是,这仍然是低效的,特别是当文档很长并且我从头开始添加内容时。

同样适用于'删除',每次删除一个字母时,我必须复制它后的所有内容并缩小数组大小。

使用节点而不是数组来存储内容似乎是一个同样糟糕的解决方案,就像现在每次我想在内容中做一些事情时,我必须从头开始一直走一条路。

那么在这种情况下管理内存的正确或有效方法是什么?我想要一个低级别的编程答案,例如C,这需要直接的内存分配和解除分配而没有“魔法”函数或库已经为你处理了一切。

5 个答案:

答案 0 :(得分:1)

使用内存块的链接列表听起来像一个很好的中间解决方案。每个节点将是特定大小的存储器的“页面”。要加快修改中间页面中的内容,您可以拥有一个索引数组,该数组将包含指向整个文档中绝对位置的页面指针。

只有在整个页面为空时才执行删除操作。在那一刻你应该做一些事情:

prevPage->next = nextPage;
pageFree(page_to_delete);

答案 1 :(得分:0)

一种有效的解决方案是使用循环数组列表。

http://en.wikipedia.org/wiki/Circular_buffer

在预先分配一些大小的数组之后,您还会跟踪指向列表“开头”的指针(首先是'c'的索引,然后是'l'的索引)。这样,要在开头插入或删除,您可以添加到内存的物理端并更改指针。

要索引数组,只需索引到数组[(开始指针+索引)%size]。

如果字母数量太大,您仍然需要复制到新数组。 就预分配的数量而言,不花费太多时间的系统是每次充满时将数组的大小加倍。这不会增加太多的开销。

编辑: 如果需要将数据插入列表中间,则圆形数组列表将无用。但是,将数据添加到列表的开头和结尾以及修改或访问中间位置非常有用。

答案 2 :(得分:0)

如果您想轻松处理字符插入和删除而不重复使用malloc,我认为最佳解决方案是双重链接列表。

点击这里:DoublyLinkedListExample(我在学校学到了它,但我认为这个tuto很简单地解释了它是如何工作的以及如何使用它)

这些只是带有数据的struct(节点),指向前一个元素的指针和指向下一个元素的指针。如果您不理解它是如何工作的,那么只需先查看一个简单链接列表的教程,然后就会更容易。

只是练习它,因为它一开始很难理解。继续训练,你会得到它:)

答案 3 :(得分:0)

鉴于您在澄清您的用例的评论中回复了您的内容,我的建议是考虑一个链接的内容列表,在您的纯文本示例的隐喻中,链接列表的元素是单词或段落或页面,这些词本身就是连续的数组。

虽然它们之间的导航速度不是很快,但似乎您的性能要求是快速插入和删除。通过使用小的连续单词,通过控制小O(n)来最小化重新分配/收缩和复制内容的n成本。这是通过使用许多n来实现的,这些是链接列表元素。

这样可以将内容空间位置的“个别”部分与性能改进相结合,同时允许您选择上层列表/树结构以帮助获得时间局部性的好处。

这真正没有解决的一件事是在处理完数据之后需要对这些数据做些什么,以及真正可以容忍的性能水平。持续的malloc调用对于延迟是不利的,因为它是一个阻塞系统调用;因此,您可以进一步考虑使用已经提到的其他解决方案,例如循环缓冲区或管理您自己更大的内存块,以便将自己分配给这些元素。通过这种方式,当您需要更大的内存块时,您只需要malloc,并且仍然不一定要在页面之间重新复制所有内容,而只需要一个不适合的较小块。

正如我在评论中所说,人们撰写有关此类事物的论文,并且它是操作系统设计和系统理解的主要组成部分。所以用一粒盐就可以了。有很多事情要考虑,这里无法涵盖。

答案 4 :(得分:0)

目前还不完全清楚你的用例是什么。

由于你提到文本操作并具有有效的插入,删除和随机访问操作,我想你可以使用rope data structure,这是一个二进制树,它基本上在其节点中存储短字符串片段(粗略地)。有关详细信息,请参阅链接的文章。