免费如何知道自由多less?
在C编程中,你可以传递任何types的指针作为自由参数,它如何知道分配内存的大小以释放? 每当我传递一个函数的指针,我也必须通过大小(即10个元素的数组需要接收10作为参数来知道数组的大小),但我不必传递的大小免费function。 为什么不,我可以在自己的函数中使用这种相同的技术,以免我需要在数组长度的额外variables之间进行购物。
当你调用malloc()
,你指定了分配的内存量。 实际使用的内存量稍多于此,并包含logging(至less)该块有多大的额外信息。 您不能(可靠地)访问其他信息,也不应该:-)。
当你打电话给free()
,它只是看额外的信息来找出块有多大。
C内存分配函数的大多数实现将为每个块存储会计信息,可以是在线或分开的。
一种典型的方式(内联)是实际分配一个头部和你要求的内存,填充到一定的最小尺寸。 例如,如果你要求20个字节,系统可以分配一个48字节的块:
- 包含大小,特殊标记,校验和,指向下一个/上一个块的指针的16字节标题等等。
- 32个字节的数据区(你的20个字节填充到16的倍数)。
那么给你的地址就是数据区的地址。 然后,当你释放这个块时, free
会简单地把你给的地址,假设你没有塞满这个地址或者周围的内存,那么在它之前检查一下会计信息。 从graphics上来说,这将是:
____ The allocated block ____ / \ +--------+--------------------+ | Header | Your data area ... | +--------+--------------------+ ^ | +-- The address you are given
请记住头和填充的大小是完全实现定义的(实际上,整个东西是实现定义的(a),但是在线会计选项是常见的)。
会计信息中存在的校验和和特殊标记通常是错误的原因,例如,如果您覆盖它们或释放它们两次,则会出现“内存舞台损坏”或“双重释放”等错误。
填充(使分配更有效率)是为什么有时你可以写一点点,超出你的请求空间的一端,而不会造成问题(不要这样做,这是不确定的行为,仅仅因为它有时候工作,这意味着可以这样做)。
(a)我已经在embedded式系统中编写了malloc
实现,无论你要求什么(这是系统中最大的结构的大小),你得到128字节,假设你要求128字节或更less(请求更多会遇到一个NULL返回值)。 一个非常简单的位掩码(即,不在线)被用来决定是否分配一个128字节的块。
我开发的其他人拥有16字节块,64字节块,256字节块和1K块的不同池,同样使用一个位掩码来决定使用或可用的块。
这两个选项都设法减less了会计信息的开销,增加了malloc
和free
的速度(在释放时不需要合并相邻的块),这在我们工作的环境中尤为重要。
从comp.lang.c
常见问题列表: 免费如何知道有多less字节?
malloc / free实现会记住每个块在分配时的大小,因此在释放时没有必要提醒它的大小。 (通常情况下,大小存储在分配的块的旁边,这就是为什么如果分配的块的边界甚至被略微超出,通常会破坏)
这个答案是从free()如何知道要释放多less内存? 在那里,我被严格禁止回答一个明显重复的问题。 这个答案应该与这个重复相关:
对于malloc
的情况,堆分配器将原始返回指针的映射存储到稍后free
内存所需的相关细节。 这通常涉及以与使用中的分配器相关的任何forms存储存储器区域的大小,例如原始大小,或用于跟踪分配的二叉树中的节点,或正在使用的存储器“单元”的数量。
如果您“重命名”指针,或以任何方式复制指针,则free
不会失败。 然而,这不是参考数字,只有第一个free
是正确的。 额外的free
是“双免费”的错误。
尝试free
与以前的malloc
返回的值不同的任何指针,但尚未确定是错误。 部分释放从malloc
返回的内存区域是不可能的。
malloc()
和free()
依赖于系统/编译器,所以很难给出具体的答案。
有关这个其他问题的更多信息。
在一个相关的说明GLib库有内存分配函数,不保存隐式大小 – 然后你只是传递大小参数释放。 这可以消除部分开销。
当您调用malloc
时,堆pipe理器会将属于已分配块的内存量存储在某处。
我从来没有自己实现过一个,但是我猜在分配块前的内存可能包含元信息。
回答你的问题的后半部分:是的,你可以,在C中一个相当普遍的模式是:
typedef struct { size_t numElements int elements[1]; /* but enough space malloced for numElements at runtime */ } IntArray_t; #define SIZE 10 IntArray_t* myArray = malloc(sizeof(intArray_t) + SIZE * sizeof(int)); myArray->numElements = SIZE;
最初的技术是分配一个稍大的块,并在开始时存储大小,然后给应用程序剩下的博客。 额外的空间保存一个大小,并可能链接到空闲块一起重用。
这些技巧有一些问题,但是,如高速caching和内存pipe理行为。 在块中使用内存往往会不必要地分页,而且会造成脏页面,从而使共享和写入时复制变得复杂。
所以更先进的技术是保持一个单独的目录。 在内存区域使用相同的二次幂的尺寸的情况下,也开发了一些奇特的方法。
一般来说,答案是: 分配一个单独的数据结构来保持状态。
使用malloc()或calloc()或realloc()分配的内存。
void free(void * ptr);
自由函数不接受大小作为参数。 free()函数如何知道只要一个指针就可以释放多less内存?
以下是存储内存大小的最常用方法,以便free()知道要释放的内存大小。
内存分配完成后,分配的实际堆空间大于请求内存的一个字。 额外的单词用于存储分配的大小,稍后由free()使用
当我们调用malloc时,它只需要消耗更多的字节。 这更多的字节消耗包含检查总和,大小和其他附加信息的信息。 当我们在那个时候免费通话的时候,它直接去找那个地址的附加信息,并且find多less空闲空间。