为什么free()时不需要传递大小

malloc()和free()是c中两个非常基本的函数,但这种最基本的东西往往都是特别复杂的。
malloc和free的原形如下:

void *malloc(unsigned int num_bytes);
void free(void *ptr);

在c的标准中并没有定义这两个函数的具体实现,在我们最常用的gcc中,malloc使用的是ptmalloc的实现,最早由Doug Lea完成,并被Wolfram Gloger改进以支持多线程。
malloc的具体实现过于复杂,这里就不具体展开了。
总体上说,ptmalloc的内存管理是基于内存池的,而它的内存来源有两种:
1 通过brk()获得
2 通过mmap()匿名映射获得
这两种获得内存的方式分别对应于进程地址空间的不同部分。64位linux进程的默认内存布局如下:


对于其中的Heap区域,就是我们通常意义上的堆空间,这部分内存将通过brk()获得。brk()的原理非常简单,只涉及指针的上下移动,也就是只分配虚拟地址空间,而不分配物理内存,当实际访问到此内存时,将触发page fault异常由操作系统完成物理内存的分配。由于操作简单,所以brk的效率非常高。
而另一个Memory Mapping Region区域,简称mmap区域,将通过操作系统的mmap()函数获得。mmap区域不仅可以提供内存的分配,还可以映射文件,比如通过mmap打开文件,或者加载so文件等等。
mmap函数的原形如下:

void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 

其中的flags,在使用mmap分配内存时,设置为MAP_ANONYMOUS,也就是匿名映射。当使用mmap()映射内存时,操作系统默认将对这块内存执行清0操作,因此相比于brk,mmap的效率相对较低。
基于内存池的内存管理,本质上都是把变长的内存分配转换为定长的内存分配。因为只有定长,才可以复用。
ptmalloc的内存池结构大致如下:


可以看出,内存的分配将根据实际的大小,选择定长块。比如请求的内存是23字节,那么将分配一块24字节的内存,而请求的如果是25字节,那么将分配一块32字节的内存(对于大于512字节的数据,统一存储在large bin中)。具体的分配策略就不展开了。
每一种大小的内存,都组成了一个一个的队列,在这些队列里维护了一个双向链表,将所有的小块内存串联起来。每一个小块内存(chunk)的结构如下:


上面的这个结构是一块在使用中的内存的状态。其中的mem部分,则是返回给用户的void*指针位置。而最开始的两个结构:size of previous chunk,和 size of chunk,则用于维护全局内存的链表。
之所以说是全局内存的链表,是由于内存分配时是先向系统请求一个比较大的内存块(64位系统一般为64Mb),之后从这64Mb内存中切出用户需要的大小分配给用户。而为了维护分配出去的内存块之间的关系,通过前两个结构来使所有内存块构成一个大的链表,当回收内存时,通过这个全局链表,将所有空闲内存组合起来,还给操作系统,其中有3个标记位:A,M,P,P标识前一块内存是否空闲。
下面的结构就是一块空闲内存的状态:

相比于使用中的状态,空闲部分的内存增加了4个新的结构(Forward pointer to next chunk in list 等,其中fd_nextsize和bk
_nextsize只存在于large bin中),这4个结构用于维护每个定长内存队列的双向链表结构,这个链表的存在主要是为了分配时查找内存时足够便利,可以基本上保证分配内存时的平均复杂度维持在O(1)。

在有了前面所有的介绍之后,可以总体上描述一下malloc和free的基本流程:
当用户向ptmalloc请求内存时:
1 首先查找定长内存分配池,如果查找到则返回
2 如果没有空闲内存可供使用,则向操作系统申请一块64Mb的内存,从中切出用户需要的内存,返回
当用户调用free释放内存时:
1 直接将内存放入适当的定长内存池队列
2 如果触发了一定的条件,则将所有空闲内存合并,如果满足释放条件,将内存全部还给操作系统

当然了,上面的描述中省略了太多的细节。比如什么时候走brk什么时候走mmap, 再比如当请求的内存大于一个阙值时,ptmalloc将会变成一个mmap的简单封装,还有触发内存归还操作系统的条件等等。
不过已经足够回答题目中的问题了:因为malloc的时候记录了大小。
这里还可以得出另一个结论:由于malloc的时候记录了大量的状态,所以在频繁使用malloc分配小内存时,会造成大量的内存浪费。举例来说,当反复malloc(1)时,每一次分配的内存在32字节:包括size of previous chunk,size of chunk,bk_chunk_pointer,fd_chunk_pointer共4个指针,合计4 * 8 = 32字节....

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • C/C++程序为什么比起其它语言开发的程序效率要高,一个很重要的原因就是可以直接操作内存,今天就来讲讲为什么...
    耐寒阅读 4,306评论 0 8
  • Linux内存空间简介 32位Linux平台下进程虚拟地址空间分布如下图: Linux提供了如下几个系统调用,用于...
    90后老码农阅读 11,378评论 2 14
  • linux内存寻址 3种地址:虚拟地址、物理地址、逻辑地址物理地址:内存的电路地址,对应内存地址线上的高低电平,物...
    grimlock44阅读 1,114评论 0 1
  • 最近开始入坑linux下的堆漏洞成因与利用方式,首先从认识堆开始,一步步为自己的学习做一些总结。 0x00 什么是...
    星辰照耀你我阅读 1,102评论 0 4
  • 昨天是孩子开家长会的时间,尽管我做了很多的心里建设却依然没有逃脱心态的崩裂。 对照老师在PPT上展示出来孩子的种种...
    鱼羊姑娘阅读 382评论 6 4