在C编程中,您可以将任意类型的指针作为参数传递给free,它如何知道要释放的内存的大小?每当我将指针传递给某个函数时,我都还必须传递大小(即,包含10个元素的数组需要接收10个参数作为参数来知道数组的大小),但是不必将大小传递给自由功能。为什么不这样做呢?我可以在自己的函数中使用相同的技术来使我免于需要购买数组长度的额外变量的麻烦吗?
在C编程中,您可以将任意类型的指针作为参数传递给free,它如何知道要释放的内存的大小?每当我将指针传递给某个函数时,我都还必须传递大小(即,包含10个元素的数组需要接收10个参数作为参数来知道数组的大小),但是不必将大小传递给自由功能。为什么不这样做呢?我可以在自己的函数中使用相同的技术来使我免于需要购买数组长度的额外变量的麻烦吗?
Answers:
调用时malloc()
,您指定要分配的内存量。实际使用的内存量略大于此数量,并且包含额外的信息,这些信息至少记录了块的大小。您不能(可靠地)访问其他信息-也不应:-)。
当您致电时free()
,它仅查看额外信息以找出障碍物的大小。
malloc_size()
从malloc()
ed指针可靠地访问块大小。但是没有可靠,可移植的方法。
free()
要求程序员准确地报告malloc()
块有多大,您能想象到恐怖吗?内存泄漏本身已经很严重了。
malloc()
和使用free()
,但是您必须存储数组的大小?blockSize(ptr)
如果他们仍然存储信息,他们为什么不可以做类似的事情?
C内存分配功能的大多数实现都会在线或单独存储每个块的计费信息。
一种典型的方法(内联)是实际分配标头和所需的内存,并填充到一些最小大小。因此,例如,如果您要求20字节,则系统可能会分配一个48字节的块:
然后提供给您的地址就是数据区的地址。然后,当您释放该块时,free
只需使用您提供的地址,并假设尚未填充该地址或该地址周围的内存,请在该地址之前立即检查会计信息。在图形上,这将遵循以下原则:
____ The allocated block ____
/ \
+--------+--------------------+
| Header | Your data area ... |
+--------+--------------------+
^
|
+-- The address you are given
请记住,标头和填充的大小是完全由实现定义的(实际上,整个事情都是由实现定义的(a),但内联记帐选项是常见的)。
如果您覆盖它们或将它们释放两次,则核对信息中存在的校验和和特殊标记通常是导致错误的原因,例如“内存区域损坏”或“双重释放”。
填充(以提高分配效率)是为什么有时您可以在请求的空间末尾写一点而不引起问题的原因(仍然,不要这样做,这是未定义的行为,并且因为有时可以工作,所以没有这样做)并不意味着可以这样做)。
(a)我已经编写malloc
了嵌入式系统的实现,其中无论您要什么(系统中最大结构的大小),您都会得到128个字节,假设您要求的字节数不超过128个字节(要求更多)返回值为NULL)。使用非常简单的位掩码(即,非串联)来确定是否分配了128字节的块。
我开发的其他程序针对16字节块,64字节块,256字节块和1K块具有不同的池,再次使用位掩码来确定使用或可用的块。
这两个选项都设法减少了会计信息的开销,并提高了(malloc
和free
在释放时无需合并相邻块)的速度,并且在我们正在工作的环境中尤其重要。
malloc
是,在成功的情况下,它为您提供至少与您要求的内存一样大的内存块。就如何访问其中的各个元素而言,各个块是连续的,但不要求这些块来自的领域是连续的。
void *x = malloc(200); free(x, 500);
是没有好下场的:-)在任何情况下,为了提高效率,实际的缓冲区的大小可能会更大(你就不能依靠这一点)。
从comp.lang.c
FAQ列表中:free如何知道要释放多少字节?
malloc / free实现在分配时会记住每个块的大小,因此释放时不必提醒它的大小。(通常,大小存储在所分配的块附近,这就是为什么如果所分配的块的边界甚至略微超出极限,情况通常会严重中断的原因)
free
。也许答案并不令您满意,但我认为您不会获得具有更通用的信息的方法:-)
这个答案是从释放的。free()如何知道要释放多少内存?一个明显的重复问题使我无法回答。然后,此答案应与此重复项有关:
对于的情况malloc
,堆分配器存储原始返回的指针到free
以后存储所需的相关详细信息的映射。这通常涉及以与使用中的分配器相关的任何形式存储内存区域的大小,例如原始大小,或用于跟踪分配的二进制树中的节点,或使用中的内存“单位”计数。
free
如果您“重命名”指针或以任何方式复制指针,都不会失败。但是,它不算作参考,只有第一个free
是正确的。其他free
s是“双重释放”错误。
尝试free
使用与先前malloc
s 返回的值不同且尚未释放的值的任何指针都是错误。无法部分释放从返回的内存区域malloc
。
malloc()
并且free()
依赖于系统/编译器,因此很难给出具体答案。
有关此其他问题的更多信息。
要回答问题的后半部分:是的,可以,下面是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;
当我们调用malloc时,它只是消耗了更多的字节数。这更多的字节消耗包含诸如校验和,大小和其他附加信息之类的信息。当我们在那个时候打电话给free时,它直接转到该附加信息,在该地址中找到地址并找到多少空闲块。