链表并不能解决堆中所有问题,还需要内存池

堆和栈与静态内存分配不一样,虽然都在进程地址空间内,但是它们并没有提前就分配好空间,而是在程序运行的时候进行分配,不过栈是操作系统自动分配和释放,而堆是由开发人员根据具体需求进行分配,释放,这就是我们今天的主题,内存的动态分配。

相信学过C语言直系亲属的C++、objective-C等语言的朋友们知道,在早期的时候,它们都需要手动的通过malloc函数进行分配,然后又需要手动的进行释放(oc中是alloc和dealloc),不过这样开发效率很低,往往会因为引用和内存忘记释放出现各种奇葩问题。我记得当时有人说过,用手动操作内存,其编码过程中消耗的时间要比使用ARC机制的编程语言多一倍左右。后来,随着各种新的编程语言的出现,其中又增加各种新的思维方式,有了ARC等垃圾自动回收机制后,在编码过程中,编程人员不用再为内存的释放而操心,大大加快了编程速度,降低了编程的门槛。不过有一点要注意,C++和C至今还是没有官方的ARC机制,不排除有大佬自己实现。

不过就我从以前学习objective-C时学习的MRC和后来使用的ARC来说,编码速度确实使用ARC来的快,但是编译和软件的使用效率上看,ARC更容易出现卡顿等现象,说简单点,就是没有以前那么顺畅。如果多翻一翻GitHub上的一些大佬写的项目,就会发现这些项目中,在比较关键的地方仍然使用MRC机制,手动的管理内存的引用和释放(Java很早就出现垃圾自动回收机制了)。我个人觉得培训班之所以能够批量生产编码员,就是因为现在语言不再让程序员需要去考虑内存管理等问题,全部交给计算机去处理了。

我们上面说了很多MRC和ARC等机制,实际上万变不离其宗,终究是对内存进行动态的分配和释放,所以我们先来说内存的分配和释放。我们在说数组的时候遇到过这样的问题,本来我们的数组要放是个元素,但是后来需要向里面增加其他几个元素,这时候,我们前面使用的基本数组类型的长度是不能变的,所以会出现不能储存的问题,这时候怎么办呢,于是就需要我们自己取申请一个可变长的的数组。静态分配?不行,早早就给把内存空间分配好了。栈?这也不行,我们在定义基本数据类型变量时已经告诉数组长度,系统也给分配好了,还想变,不可能。那么我我们就只剩下堆了,堆是我们编程人员可以控制的一片区域空间,所以我想申请多大空间就可以申请多大空间,不过一般来说,在分配内存的时候,我们不需要告诉计算机我们需要多大的内存,毕竟在不同的操作系统上,一个数据类型的长度是不同的。需要注意的是,在我们分配了内存后,就必须要将其释放掉,否则数据会一直存在,直到程序结束,如果不释放,内存就会渐渐变满,是不是就出现问题了,所以在内存操作的时候一定要记住一个成语:“有始有终”。

通过上面的描述,我们是不是就可以看到这三种内存分配模式的效率问题了。静态内存是在程序启动时就已经分配好了,程序在运行过程中直接拿来用。栈是需要等待程序运行时自动分配和释放。但是堆的话,既不能在程序启动时分配空间,又不能在程序运行时提前分配空间,只能等待在需要的时候增加内存或减少内存。这样看来,静态内存分配效率最快,然后是栈,最后才是堆。

链表

当然,对只是内存的分配,函数才是我们操作内存的主要手段,在C语言中,能够动态内存分配的函数有malloc(常用),Calloc(分配连续的一块内存)、realloc(重新分配内存大小)、free(释放上面所申请的内存),那么这些函数是怎么实现在堆上的内存申请和释放呢,首先,堆的内存并不是连续不断的,它在申请的时候会向系统申请一块内存空间,当这片内存空间用完后,它会向系统继续申请另一块空间,这时候系统会从低地址向高地址遍历,如果出现大小合适的空闲空间,那么就会通过我们前面所说的指针进行连接,这种方式是不是和链表一个道理,所以在学习C语言的时候,总是会提倡要求了解链表的概念和实现方式。当然,这种方式是有弊端的,当链表中指针被破坏时,堆就会出现问题,被分开的内存空间可能会被其他程序越界读取和使用,而且长期对内存进行遍历,数据小时还行,当数据达到一定规模后,每次进行遍历,都需要消耗大量时间,所以就有了新的理论和观点,就是我们说的内存池,内存池主要讲的并不是内存的申请和分配问题,而是对自己内存的管理,不过这个内存池管理的原理比较复杂。我们前面说的ARC和MRC实际上就是对内存池的管理,当申请内存空间时,在池子中对这个对象进行引用加一,这片内存空间没有任何引用时,才正式释放掉,这就是我们常说的“内存垃圾回收机制”。

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

推荐阅读更多精彩内容

  • 内存管理 简述OC中内存管理机制。与retain配对使用的方法是dealloc还是release,为什么?需要与a...
    丶逐渐阅读 1,928评论 1 16
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,068评论 1 32
  • 为什么管理内存: 程序在运行的时候,要创建大量的对象,这些对象放在堆和栈上。(基本类型放在栈上,由系统自动管理。)...
    我是谁重要吗阅读 1,365评论 0 12
  • 帮师妹和一个球友牵线成功,他们一直想请我吃饭。我说,请我吃饭不如请我打球,请吃饭你浪费钱财、我浪费时间,但是那天我...
    考拉王的桉树阅读 422评论 0 1
  • 天地无绝,万物无绝,绝境无绝,生生不息,不息生生。
    21xd阅读 74评论 0 0