Block 之 Block内存管理
前言
block的内存管理相对比较复杂,分ARC和MRC两种情况考虑,虽然现在开发基本是用ARC,编译器已经帮我们做了很多内存管理的优化,但我们不仅要知其然,也要知其所以然。
Block的类型
根据Block的存储方式,分为以下三种:
.
NSConcretStackBlock
.
NSConcretGlobalBlock
.
_NSConcretMallocBlock
这三种类型表明了Block的三种存储方式:栈、全局、堆。
注意: 在ARC模式下,Block只存在全局和堆之中,对于栈上的Block,编译器帮我们拷贝到堆上,这也是为什么我们声明Block的时候即使不声明为copy,Block也是拷贝到堆上。显示地声明不会与编译器相冲突,是为了我们更好地理解是编译器做了copy这一步使得Block拷贝到堆上。
全局Block
位于全局存储区的Block有两种情况:
.
定义在函数外面的Block;
1 2 3 |
|
.
不引用局部变量的Block;
1 2 3 4 5 6 7 8 9 10 |
|
栈Block
1 2 3 4 5 6 |
|
上面的例子在MRC下无法编译,而在ARC下可以编译
这是因为返回block的时候是返回局部变量的指针,而这一点恰是编译器已经断定了。在ARC下可以编译过,是因为ARC使用autorelease了
堆Block
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
在MRC模式下,会发生异常,因为数组中的block是在栈上的,到blk指向的block已经释放内存了,访问blk就会造成崩溃,解决方法就是在block后面加上copy,使它变成堆上的block。
copy的使用
不管block配置在何处,用copy方法复制都不会引起任何问题。
在ARC环境下,如果不确定是否要copy block尽管copy即可。ARC会自动处理的。
【注意】:
● 在栈上调用copy那么复制到堆上
● 在全局block调用copy什么也不做
● 在堆上调用block 引用计数增加