我有一个关于 heap
和 malloc
的简单问题:
当我们使用 malloc
分配一些内存空间,如下所示:
int *p;
p = (int*) malloc (10*sizeof(int));
实际上,在堆中分配了10个单词的空间。然而,我的问题是:
实际使用的内存空间是否真的是10个单词?
还是需要其他额外的空间来存储内存大小的值?
甚至,由于堆被构造为链表,是否还有其他的内存空间用于存储指向堆中下一个节点的地址?
我有一个关于 heap
和 malloc
的简单问题:
当我们使用 malloc
分配一些内存空间,如下所示:
int *p;
p = (int*) malloc (10*sizeof(int));
实际上,在堆中分配了10个单词的空间。然而,我的问题是:
实际使用的内存空间是否真的是10个单词?
还是需要其他额外的空间来存储内存大小的值?
甚至,由于堆被构造为链表,是否还有其他的内存空间用于存储指向堆中下一个节点的地址?
这完全取决于实现。
a) 每个已分配节点之前可能有几个字节,其中包含节点的大小、指向下一个节点的指针,以及可能是前一个节点指针和节点类型。
b) 返回的项可能除了其他分配之外没有任何东西。另一个结构在别处跟踪已分配和空闲的内容,可能通过位图或小型并行列表来完成。
c) 另一种变体提供几个固定大小块的数组。一个数组可以提供32字节块;另一个是128字节块等等。每个数组的位图管理分配。
d) 我见过的最基本的实现完全忽略了 free()
(也就是说,free()
是一个无操作),并在每个 malloc()
上分配池的下一个部分。
到目前为止,最常用的现代技术是 a。变体 b 在许多文件系统中使用,如 NTFS 和 FAT。选项 c 在许多 DEC 操作系统中特别喜爱,尤其是用于内核。选项 d 被一些极简主义嵌入式环境所使用,并带有适当的警告。
在大多数实现中,请求的分配被舍入到某个自然的倍数(通常是 2、8、16 等)方便算法。因此,一系列分配的大小为 5、3、8、7、4、1 和 15 可以被视为每个 16 字节的请求。
sbrk()
是乐观的,并可能导致malloc()
的乐观,对吗? - wallykmalloc()
和其他函数是否真正“使用”了内存,当实际使用发生时,“额外的内存”可能会改变,而实际上只是标记为已使用但尚未使用。请参见这里。如果这不能帮助你,就不要费心回答了。注意:乐观分配是与sbrk()
的概念是不同的。 - chux - Reinstate Monica内存分配取决于编译器库和操作系统。
这两种语言都没有规定可以分配的最大内存量。您保证的仅是所请求的大小。
因此,如果有任何额外的内存分配,它将取决于平台。
另外,分配更大的空间时可能会减少开销。
尝试编写自己的内存分配器,并查看所需内容,特别是在处理内存时。
malloc
的代码可以分配比你请求的内存稍微多一点的空间,将已分配内存的大小存储在已分配内存的开始位置,然后给你一个指向下一个内存地址的指针。当你使用该指针调用free
时,分配器会回到前面一点,读取缓冲区的大小,并计算需要释放多少空间。malloc
分配内存时,你只会得到一个指向该内存中第一个地址的指针,并且保证已经为你分配了这么多字节供你使用。内存分配和跟踪的细节是依赖于平台的,你无法从程序内部访问这些信息。因此,虽然可能会为开销目的分配额外的内存,但你无法以跨平台的方式使用这些知识。malloc
失败的情况并不适用于这个问题。 - Sam Estep