当存储块的请求不是2的幂时,会发生什么?

假设我们对大小为n的内存块做一个malloc请求,对于k> 0,其中2 ^ k!= n。 Malloc为这个请求的内存块返回空间,但是如何处理页面中的这个剩余缓冲区。 我读的页面通常是两个权力的内存块。

维基指出以下内容:

Like any method of memory allocation, the heap will become fragmented; that is, there will be sections of used and unused memory in the allocated space on the heap. A good allocator will attempt to find an unused area of already allocated memory to use before resorting to expanding the heap. 

所以我的问题是如何跟踪?

编辑:如何使用malloc跟踪未使用的内存?

正如Morten Siebuhr所指出的那样,这取决于具体的实施。 在非常简单的情况下,可能会有一个免费的,固定大小的内存块(可能全部具有相同的大小)的列表,所以未使用的内存被浪费了。 请注意,真正的实现永远不会使用这种简单的算法。

这是一些简单的可能性的概述: http : //www.osdcom.info/content/view/31/39/

这个维基百科条目有几个有趣的链接,包括上面的一个: http : //en.wikipedia.org/wiki/Dynamic_memory_allocation#Iplementation

作为最后一句话,使用“malloc实现”来搜索一个堆(有意义的)有价值的链接。

一个标准的BSD风格的内存分配器基本上是这样工作的:

  • 它保留了预分配的内存块的大小为2 ^ k,k <= 12(例如)的链表。
  • 实际上,给定k的每个列表都由来自不同区域的存储块组成,如下所示。
  • 通过计算n'(最接近的2 ^ k> = n),然后查找列表中的第一个区域 k,然后返回给定区域的空闲列表中的第一个空闲块。
  • 当没有为2 ^ k大小预先分配内存块时,分配一个区域,一个区域是一个较大的连续内存块,例如一个4kB的内存块。 这段内存然后被切成2 ^ k字节的块。 在连续存储区域的开始处存在簿记信息,例如在哪里找到该区域内的空闲块的链接列表。 也可以使用位图,但链接列表通常具有更好的缓存行为(您希望下一个分配的块返回已存在于缓存中的内存)。
  • 使用区域的原因是免费(ptr)可以有效地执行。 在这个例子中,ptr&0xfffff000指向包含簿记结构的区域的开始,并且可以将存储块链接回该区域。
  • BSD分配器会浪费空间,总是返回一个大小为2 ^ k的内存块,但是它可以重用块的内存来保留空闲列表,这是一个不错的属性。 分配速度也非常快。

上述总体思路的修改包括:

  • 使用匿名mmap进行大型分配。 这将工作转移到内核来处理大型malloc,并避免在这些情况下浪费大量内存。
  • malloc的GNU版本有两个非幂次桶的特殊情况。 在BSD分配器中没有任何内在的东西需要返回2 ^ k的内存块,只有存在预定义的桶大小。 GNU分配器有更多的桶,因此浪费更少的空间。
  • 在线程之间共享内存是一个棘手的问题。 分配过程中的锁争用是一个重要的考虑因素,所以在GNU分配器中,例如,如果在分配过程中遇到锁争用,就会为给定的桶大小急切地为不同的线程创建额外的区域

从实施到实施,这个变化很大 。 有些人会浪费空间,一些细分的页面,直到他们得到所需的大小(或接近它)&c。

如果您是出于好奇,我建议您阅读有关实施的源代码,

如果是因为性能方面的担忧,请尝试对其进行基准测试,看看会发生什么。