iOS 堆和栈

heap(堆)和stack(栈)是内存管理的两个重要概念。在这里我们指的不是数据结构上面的堆与栈,在这里指的是内存的分配区域。

了解堆、栈,有助于更好地理解参数传递,多态,线程,异常和垃圾收集。

stacknheap.png

栈(堆栈/stack)

stack的空间由操作系统进行分配,分配发生在连续的内存块上,向低内存地址堆扩展的

在现代操作系统中,一个线程会分配一个stack,当线程退出堆栈时回收. 当一个函数被调用,一个stack frame(栈帧)就会被压到stack里。里面包含这个函数涉及的参数,局部变量,返回地址等相关信息。当函数返回后,这个栈帧就会被销毁。而这一切都是自动的,由系统帮我们进行分配与销毁。对于程序员是透明的,我们不需要手动调度。

堆(heap)

heap的空间需要手动分配,堆是向高地址扩展的数据结构

heap与动态内存分配相关,内存可以随时在堆中分配和销毁。我们需要明确请求内存分配与内存销毁。 简单来说,就是malloc与free。应用程序通常只有一个堆。

内存不足问题更可能发生在堆栈中,而堆内存中的主要问题是碎片和内存泄漏问题

栈 VS 堆

堆栈更快,因为访问模式使得从中分配和释放内存变得微不足道(指针/整数简单地递增或递减),而堆在分配或释放中涉及更复杂的簿记。此外,堆栈中的每个字节都经常被频繁地重用,这意味着它往往被映射到处理器的缓存,使其非常快。堆的另一个性能损失是堆(主要是全局资源)通常必须是多线程安全的,即每个分配和释放需要 - 通常 - 与程序中的“所有”其他堆访问同步。

Objective-C中的Stack和Heap

首先所有的Objective-C对象都是分配在heap的。 在OC最典型的内存分配与初始化就是这样的。

NSObject *obj = [[NSObject alloc] init];

一个对象在alloc的时候,就在Heap分配了内存空间。

stack对象通常有速度的优势,而且不会发生内存泄露问题。那么为什么OC的对象都是分配在heap的呢? 原因在于:

  • stack对象的生命周期所导致的问题。例如一旦函数返回,则所在的stack frame就会被摧毁。那么此时返回的对象也会一并摧毁。这个时候我们去retain这个对象是无效的。因为整个stack frame都已经被摧毁了。简单而言,就是stack对象的生命周期不适合Objective-C的引用计数内存管理方法。
  • stack对象不够灵活,不具备足够的扩展性。创建时长度已经是固定的,而stack对象的拥有者也就是所在的stack frame

关于Block

为什么block需要使用copy修饰符?

block在创建时是stack对象,如果我们需要在离开当前函数仍能够使用我们创建的block。我们就需要把它拷贝到堆上以便进行以引用计数为基础的内存管理。

最终得到的答案是这与block对象在创建时是stack对象有关。
所以,其实Objective-C是有它的Stack object的。是的,那就是block.

在Objective-C语言中,一共有3种类型的block:

  • _NSConcreteGlobalBlock 全局的静态block,不会访问任何外部变量。
  • _NSConcreteStackBlock 保存在栈中的block,当函数返回时会被销毁。
  • _NSConcreteMallocBlock 保存在堆中的block,当引用计数为0时会被销毁。

这里我们主要基于内存管理的角度对它们进行分类。

  • NSConcreteGlobalBlock,这种不捕捉外界变量的block是不需要内存管理的,这种block不存在于Heap或是Stack而是作为代码片段存在,类似于C函数。
  • NSConcreteStackBlock。这就是这次探索的重点了,需要涉及到外界变量的block在创建的时候是在stack上面分配空间的,也就是一旦所在函数返回,则会被摧毁。这就导致内存管理的问题,如果我们希望保存这个block或者是返回它,如果没有做进一步的copy处理,则必然会出现问题。
  • NSConcreteMallocBlock,因此为了解决block作为Stack object的这个问题,我们最终需要把它拷贝到堆上面来。而此时NSConcreteMallocBlock扮演的就是这个角色。
    拷贝到堆后,block的生命周期就与一般的OC对象一样了,我们通过引用计数来对其进行内存管理。
ARC

在ARC情况下,创建的block仍然是NSConcreteStackBlock类型,只不过当block被引用或返回时,ARC帮助我们完成了copy和内存管理的工作。

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

推荐阅读更多精彩内容

  • objective-c 对象所占内存总是分配在“堆空间”,并且堆内存是由你释放的,即release。一般由程序员分...
    ikonan阅读 390评论 0 0
  • 在操作系统ios中应用程序使用的计算机内存不是统一分配内存空间的。 运行代码使用的内存空间在三个不同的内存区域,分...
    rightmost阅读 928评论 0 0
  • 星期一就迫不及待地等星期五的到来,每天划水,混吃等死,这就是很多人的工作状态。工作对于我们来说没有什么成就感,也不...
    张半仙读书笔记阅读 362评论 0 1
  • 我们奋斗一生带不走一草一木我们执着一生带不走一分虚荣爱慕今生,无论贵贱贫富总有一天都要走到这最后一步 到了后世,霍...
    娚稀妹子阅读 231评论 0 2
  • 你真的快乐吗? 每当听到这个问题时,我都会毫不犹豫地回答到"快乐啊”。这个问题看起来似乎很好回答,却又不那么确定。...
    弌氺阅读 399评论 0 0