自由指针使用的长度值(整数)
正如我们所知,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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我们不知道 malloc 内部是如何工作的。它可以根据运行时库的版本而变化。 (到目前为止)还没有,这不是赌博的理由。
我们不应该依赖任何特定实现的特定幕后行为。仅依赖于记录的功能,除非您愿意为了某些有价值的目的而牺牲通用性。
事实上,大多数 malloc 实现都会在分配给程序的区域之前立即分配额外的几个字的开销。开销允许管理堆。但是size字段是之前的4个字节,还是16个字节?它是 32 位值吗?也许它是按比例缩放的段落数(16 字节条目),就像 iRMX86 上的那样。开销区域是否包含前向链接和后向链接?也许有一个带有库的调试版本的名称检查字段。
也许它像 Cyber/NOS 上的 Snobol-68 一样实现:带有指向数据及其大小的指针的结构数组。程序“指针”实际上是数组中项目的索引。对于缓存和预读来说,这是一种特别有效的结构。
可能的变化如此之多,任何持久的程序都不应该依赖这些细节。
您可能会考虑编写一个
lengthof(ptr)
函数来包含在运行时库中,该函数返回malloc()
请求的字节数,或者可能是实际分配的字节数。We do not know how malloc works internally. It can change from version to version of the runtime library. That it hasn't (so far), it not a reason to gamble.
We should not depend on specific behind-the-scenes behavior of any particular implementation. Only depend on the documented features unless you are willing to trade generality for some worthy purpose.
Most
malloc
implementations do, in fact, allocate an extra few words of overhead immediately before the area given to the program. The overhead allows administrating the heap. But is the size field 4 bytes before, or 16? Is it a 32 bit value? Maybe it is a scaled number of paragraphs (16-byte entries), like on iRMX86. Does the overhead area contain forward links and backward links? Maybe there is a namecheck field with the debug version of the library.Maybe it is implemented like Snobol-68 on Cyber/NOS: an array of structure with pointers to data and their sizes. Program "pointers" are actually indices of the item in the array. This is an especially efficient structure for caching and readahead purposes.
There are so many possible variations that no enduring program should rely on such details.
Possibly, you might consider writing a
lengthof(ptr)
function to include with the runtime library which returns the number of bytes requested atmalloc()
, or maybe actually allocated bytes.大多数
malloc
实现可能确实有某种方法来查找指针参数的分配大小。但是,执行此操作的方法是实现私有的,并且某些
malloc
实现并不总是为每个区域分配前缀标头。实现 malloc 的一个常见技巧是处理不同的分配大小。例如,它可以以不同的方式处理
malloc
(即2*sizeof(void*)
),因为这种情况非常常见(例如单链接)指针列表,如 Lisp 中的cons
单元格)。malloc
小尺寸区域,大小小于阈值,通常是页面大小 - 在 getpagesize(2) 系统调用,通常为 4kbytes。malloc
一些实现考虑了实际地址,例如有一个专用于对的内部区域(页面段),另一个专用于小区域的分配区域大小为
2^n
和3*2^n
的区域(例如n>2 && n<10
),并且大对象实际分配在自己的每个竞技场。然后,malloc
实现有一些内部哈希表将地址(每个低 16 位全为零)映射到竞技场。因此,您不应该假设每个 malloc 区域之前都有开销。这可能是错误的。如果您需要这样的假设,请使用操作系统调用编写您自己的
malloc
等效项(或替换项)(例如 mmap(2)(Linux 上)。It is probably true that most
malloc
implementations have some way to find the allocated size of a pointer argument.However, the way to do that is private to the implementation, and some
malloc
implementation don't always allocate a prefix header for each zone.A common trick for implementing
malloc
is to handle differently various allocated sizes. For instance, it could handle differentlymalloc
of two words or less (i.e. of2*sizeof(void*)
) since this case is very frequent (for e.g. single-linked list of pointers, likecons
cells in Lisp).malloc
of small-sized zones, of size less than a threshold, typically the page size -in the sense of getpagesize(2) syscall on Linux, often 4kbytes.malloc
of large-sized zones, bigger than a page sizeSome implementations take into account the actual address, by e.g. having an internal arena (segments of pages) dedicated for pairs, another allocation arena dedicated to small sized zones of size
2^n
and3*2^n
(with e.g.n>2 && n<10
), and the large objects actually allocated in their own arena each. Then themalloc
implementation has some internal hash table mapping addresses (each of lower 16 bits all zero) to arenas.So you should not assume that each malloc-ed zone has an overhead before. It could be wrong. If you need such an assumption, write your own
malloc
equivalent (or replacement) using the operating system calls (e.g. mmap(2) on Linux).