In C programming, you can pass any kind of pointer you like as an argument to free, how does it know the size of the allocated memory to free? Whenever I pass a pointer to some function, I have to also pass the size (ie an array of 10 elements needs to receive 10 as a parameter to know the size of the array), but I do not have to pass the size to the free function. Why not, and can I use this same technique in my own functions to save me from needing to cart around the extra variable of the array's length?
当前回答
要回答第二个问题,是的,您可以(某种程度上)使用与malloc()相同的技术 通过简单地将每个数组中的第一个单元格分配给数组的大小。 这样就可以在不发送额外size参数的情况下发送数组。
其他回答
来自comp.lang.c常见问题列表:free如何知道释放多少字节?
malloc/free实现在分配每个块时记住它的大小,因此在释放时不需要提醒它大小。(通常,大小存储在已分配块的相邻位置,这就是为什么如果已分配块的边界稍有超出,情况通常会很糟糕)
Malloc()和free()依赖于系统/编译器,所以很难给出一个具体的答案。
更多关于这个问题的信息。
与此相关的是,GLib库具有不保存隐式大小的内存分配函数——然后您只需将size参数传递给free即可。这可以减少部分开销。
大多数C内存分配函数的实现都将为每个块存储记帐信息,或者内联存储,或者单独存储。
一种典型的方法(内嵌)是实际分配头部和您要求的内存,填充到某个最小大小。例如,如果你需要20个字节,系统可能会分配一个48字节的块:
包含大小、特殊标记、校验和、指向下一个/上一个块的指针等的16字节报头。 32字节的数据区(你的20字节填充为16的倍数)。
然后给您的地址就是数据区域的地址。然后,当你释放区块时,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的速度(释放时不需要合并相邻的块),这在我们工作的环境中特别重要。
回答你问题的后半部分:是的,你可以,在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;
推荐文章
- 为什么函数指针定义可以使用任意数量的&号或星号* ?
- 什么是可重入函数?
- 如何在C中将数组初始化为0 ?
- Typedef定长数组
- 在C语言中通过引用传递
- sizeof(某个指针)总是等于4吗?
- 为什么星号在变量名之前,而不是在类型之后?
- 何时使用内联函数,何时不使用它?
- 在C语言中如何比较结构是否相等?
- 在套接字编程中AF_INET和PF_INET的区别是什么?
- #在C中定义打印调试宏?
- 我应该使用static_cast或reinterpret_cast时,铸造一个void*到什么
- read()和recv(), send()和write()之间有什么区别?
- 为什么0 < -0x80000000?
- 静态const vs #define