从堆栈剖析block为什么用copy

1.首先理解连个概念

堆:heap ->

heap的空间需要手动分配。

heap与动态内存分配相关,内存可以随时在堆中分配和销毁。我们需要明确请求内存分配与内存销毁。

简单来说,就是mallocfree.

栈:stack-> 

stack的空间由操作系统进行分配。

  在现代操作系统中,一个线程会分配一个stack.

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


所有的OC对象都是分配在heap中的,一个对象在alloc的时候就已经分配好了内存空间  


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

原因在于:


1. stack对象的生命周期所导致的问题。例如一旦函数返回,则所在的stack frame就会被摧毁。那么此时返回的对象也会一并摧毁。这个时候我们去retain这个对象是无效的。因为整个stack frame都已经被摧毁了。简单而言,就是stack对象的生命周期不适合Objective-C的引用计数内存管理方法。


2. stack对象不够灵活,不具备足够的扩展性。创建时长度已经是固定的,stack对象的拥有者也就是所在的stack frame


现在就是block的问题,在以前用block修饰的时候一直用strong 查看资料和很多源代码时发现都是用的copy  虽说没有什么错误但总归是不知道为什么这样,首先block在oc中有三中类型:

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

真正的答案:


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

也就是说ARC帮助我们完成了copy的工作,ARC,即使你声明的修饰符是strong,实际上效果是与声明为copy一样的。因此在ARC情况下,创建的block仍然是NSConcreteStackBlock类型,只不过当block被引用或返回时,ARC帮助我们完成了copy和内存管理的工作




  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值