C 免费怎么知道要免费多少?

C 免费怎么知道要免费多少?,c,size,pointers,free,C,Size,Pointers,Free,在C编程中,您可以将任何类型的指针作为参数传递给free,它如何知道要释放的分配内存的大小?每当我传递指向某个函数的指针时,我也必须传递大小(即10个元素的数组需要接收10作为参数才能知道数组的大小),但我不必将大小传递给自由函数。为什么不呢?我可以在我自己的函数中使用同样的技术,以避免我需要绕过数组长度的额外变量吗?当您调用malloc时,堆管理器将属于分配块的内存量存储在某处 我自己从来没有实现过一个,但我猜分配块前面的内存可能包含元信息。当调用malloc()时,您指定要分配的内存量。实际

在C编程中,您可以将任何类型的指针作为参数传递给free,它如何知道要释放的分配内存的大小?每当我传递指向某个函数的指针时,我也必须传递大小(即10个元素的数组需要接收10作为参数才能知道数组的大小),但我不必将大小传递给自由函数。为什么不呢?我可以在我自己的函数中使用同样的技术,以避免我需要绕过数组长度的额外变量吗?

当您调用
malloc
时,堆管理器将属于分配块的内存量存储在某处

我自己从来没有实现过一个,但我猜分配块前面的内存可能包含元信息。

当调用
malloc()
时,您指定要分配的内存量。实际使用的内存量略高于此值,并包含记录(至少)块大小的额外信息。您无法(可靠地)访问其他信息,您也不应该:-)

当您调用
free()
时,它只需查看额外的信息以了解块有多大。

malloc()
free()
依赖于系统/编译器,因此很难给出具体的答案


更多信息。

来自
comp.lang.c
FAQ列表:


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;

在一个相关的便笺库中,内存分配函数不保存隐式大小,然后您只需将size参数传递给free。这可以消除部分开销。

这个答案是从一个明显重复的问题突然阻止我回答的地方重新定位的。该答案应与该副本相关:


对于
malloc
的情况,堆分配器存储原始返回指针到
free
稍后释放内存所需的相关详细信息的映射。这通常涉及以与正在使用的分配器相关的任何形式存储内存区域的大小,例如原始大小,或用于跟踪分配的二叉树中的节点,或正在使用的内存“单元”计数

free
如果您“重命名”指针或以任何方式复制它,则不会失败。然而,它不是参考计数的,只有第一个
空闲的
是正确的。额外的
free
s是“双重免费”错误


试图
free
任何指针的值与先前的
malloc
s返回的值不同,但到目前为止尚未释放的指针都是错误的。无法部分释放从
malloc

返回的内存区域。大多数C内存分配函数的实现将在线或单独存储每个块的记帐信息

一种典型的方法(串联)是实际分配一个标头和所需的内存,并填充到某个最小大小。因此,例如,如果您要求20个字节,系统可能会分配一个48字节的块:

  • 包含大小、特殊标记、校验和、指向下一个/上一个块的指针等的16字节头
  • 32字节数据区(将20字节填充为16的倍数)
然后给您的地址就是数据区的地址。然后,当您释放该块时,
free
将只获取您提供给它的地址,并假设您没有填满该地址或其周围的内存,检查它前面的记帐信息。从图形上看,这将大致如下:

\分配的块____
/                             \
+--------+--------------------+
|标题|您的数据区域|
+--------+--------------------+
^
|
+--给你的地址
请记住,头和填充的大小完全是由实现定义的(实际上,整个内容都是由实现定义的(a),但内嵌记帐选项是常见的)

会计信息中存在的校验和和特殊标记通常是导致错误的原因,如“内存已损坏”或“双重释放”,如果您覆盖它们或释放它们两次

填充(使分配更有效)就是为什么有时可以在请求的空间末尾之外写一点而不会引起问题的原因(尽管如此,不要这样做,这是未定义的行为,只是因为它有时有效,并不意味着可以这样做)


(a) 我已经在嵌入式系统中编写了
malloc
的实现,在嵌入式系统中,无论您要求什么,都可以得到128字节(这是系统中最大结构的大小),假设您要求的是128字节或更少(更多的请求将以空返回值满足)。一个非常简单的位掩码(即,非串联)用于决定是否分配了128字节的块

我开发的其他程序有不同的池,用于16字节块、64字节块、256字节块和1K块,同样使用位掩码来决定使用了哪些块或可用哪些块


这两个选项都设法减少了会计信息的开销,并提高了
malloc
free
的速度(释放时无需合并相邻块),在我们工作的环境中尤其重要。

最初的技术是分配一个稍大的块,并在开始时存储大小,然后将博客的其余部分交给应用程序。额外的