正如我们所知,free()
函数通过使用存储在malloc指针后面的前缀整数值来知道要从malloc内存中释放多少内存。所以我尝试了这个代码并且有两个疑问:
如果我malloc()
20个字节,然后在递减指针处打印整数值,则显示25个字节。如果我malloc()
40个字节,然后打印该值,那么我得到49个字节!
如果我试图超越并在malloc空间之后打印值,每次我得到一个存储在malloc内存最后一个旁边的大整数值。这个价值是多少?它有什么特别之处吗?
任何解释都将不胜感激。
int main()
{
int i;
int *ptr, *pr;
ptr = (int *)malloc(20);
pr = ptr;
printf("value of ptr is %p", ptr);
for(i = 0; i < 5; i++) {
ptr[i] = i + 1;
}
printf("now the values in malloc'd memory is\n");
for(i = 0; i < 5; i++) {
printf("%d\n", ptr[i]);
}
printf("value of ptr is %p\n", ptr);
pr--;
for(i = 0; i < 20; i++) {
printf("value of pr at address %p is %d\n", pr, *pr);
pr++;
}
return 0;
}
答案 0 :(得分:2)
我们不知道malloc如何在内部工作。它可以从运行时库的版本更改为版本。它没有(到目前为止),这不是赌博的理由。
我们不应该依赖于任何特定实现的特定幕后行为。除非您愿意为某些值得的目的进行交易,否则仅依赖于记录的功能。
malloc
实现确实在给予程序的区域之前分配了额外的几个开销字。开销允许管理堆。但是大小字段是4字节之前,还是16?它是32位值吗?也许它是一个缩放的段落数(16字节条目),就像在iRMX86上一样。开销区域是否包含前向链接和后向链接?也许有一个带有该库调试版本的namecheck字段。
也许它在Cyber / NOS上像Snobol-68一样实现:一个结构数组,指向数据及其大小。程序“指针”实际上是数组中项目的索引。这是一种特别有效的缓存和预读目的结构。
有许多可能的变化,没有持久的程序应该依赖这些细节。
您可能会考虑编写一个lengthof(ptr)
函数以包含在运行时库中,该库返回malloc()
请求的字节数,或者实际分配的字节数。
答案 1 :(得分:0)
大多数malloc
实现可能都有某种方法可以找到指针参数的分配大小。
但是,执行此操作的方式对于实现是私有的,并且某些malloc
实现并不总是为每个区域分配前缀标头。
实现malloc
的一个常见技巧是处理不同的各种分配大小。例如,它可以处理不同的
malloc
两个字或更少(即2*sizeof(void*)
),因为这种情况非常频繁(例如,单链接的指针列表,如Lisp中的cons
个单元格)。< / LI>
malloc
小尺寸区域,大小小于阈值,通常是页面大小 - 在Linux上getpagesize(2)系统调用的意义上,通常是4千字节。malloc
大尺寸区域,大于页面大小某些实施方案通过例如实际地址考虑实际地址。具有专用于对的内部竞技场(页面片段),专用于大小为2^n
和3*2^n
的小尺寸区域(具有例如n>2 && n<10
)的另一个分配竞技场,以及实际分配的大对象在每个人的自己的舞台上。然后malloc
实现有一些内部哈希表映射地址(每个低16位都为零)到竞技场。
因此,您不应该假设每个malloc-ed区域之前都有开销。这可能是错的。如果您需要这样的假设,请使用操作系统调用(例如Linux上的mmap(2))编写您自己的malloc
等效(或替换)。