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