我有一个关于heap
和malloc
:的简单问题
当我们使用malloc
如下分配一些内存空间时:
int *p;
p = (int*) malloc (10*sizeof(int));
它实际上在堆中分配了10个单词。然而,我的问题是:
实际使用的内存空间真的是10个单词吗?
或者还需要其他额外的空间来存储内存大小的值?
或者,甚至,因为堆的结构是链表,是否有其他内存空间用于存储指向堆中列表下一个节点的地址?
它完全依赖于实现。
a) 它可能在每个分配的节点之前有几个字节,其中包含节点的大小、指向下一个节点的指针,可能还有上一个节点指针和节点类型。
b) 返回的项可能除了其他分配之外没有其他内容。其他地方的结构可以通过位图或小型并行列表来跟踪分配的内容和空闲的内容。
c) 另一种变体提供了几个固定大小的块的阵列。一个阵列可以提供32字节的块;每个阵列的位图管理分配。
d) 我见过的最简单的实现完全忽略free()
(也就是说,free()
是一个无操作),并在每个malloc()
分配池的下一部分。
到目前为止,最常用的现代技术是a。变体b用于许多文件系统,如NTFS和FAT。选项c在许多DEC操作系统中受到青睐,尤其是在内核使用时。选项d由一些具有适当警告的极简嵌入式环境使用。
在大多数实现中,请求的分配被四舍五入到算法方便的一些自然倍数(通常为2、8、16等)。因此,一系列5、3、8、7、4、1和15的分配可能都被视为一个16字节的请求。
内存分配取决于编译器库和操作系统。
这两种语言都没有规定可以分配的最大内存量。您所能保证的只是所要求的尺寸。
因此,如果有任何额外的内存分配,它将依赖于平台。
此外,当分配更大的空间时,可能会有更少的开销。
试着编写自己的内存分配器,看看需要什么,尤其是在解压缩内存时。
是的,malloc
的实现可以实际分配比您请求的多一点的内存,在分配的内存的开头存储分配的内存大小,然后给您一个指向下一个内存地址的指针。当您在该指针上调用free
时,分配器将返回一点,读取缓冲区的大小,并计算出实际需要释放多少。
但当然,另一种可能的实现可以保留一个列表或字典,或者在引擎盖下做一些完全不同的事情,只要它能为您提供相同的指定行为。
当您使用malloc
分配内存时,您所得到的只是一个指向该内存中第一个地址的指针,并保证已经分配了这么多字节供您使用。如何分配和跟踪内存的详细信息取决于平台,您无法从程序中访问这些信息。因此,虽然额外的内存可能被分配用于开销目的,但您不能以跨平台的方式使用这些知识。