标签:block实现 栈 堆
block存储区域
这就需要引入三个名词:
● _NSConcretStackBlock
● _NSConcretGlobalBlock
● _NSConcretMallocBlock
正如它们名字说的那样,说明了block的三种存储方式:栈、全局、堆。
【要点1】定义在函数外面的block是global的;另外如果函数内部的block,但是没有捕获任何自动变量,那么它也是全局的。比如下面这样的代码:
typedef int (^blk_t)(int);
for(...){
blk_t blk = ^(int count) {return count;};
}
虽然,这个block在循环内,但是blk的地址总是不变的。说明这个block在全局段。
【要点2】一种情况在非ARC下是无法编译的:
typedef int(^blk_t)(int);
blk_t func(int rate){
return ^(int count){return rate*count;}
}
这是因为:block捕获了栈上的rate自动变量,此时rate已经变成了一个结构体,而block中拥有这个结构体的指针。即如果返回block的话就是返回局部变量的指针。而这一点恰是编译器已经断定了。在ARC下没有这个问题,是因为ARC使用了autorelease了。
【要点3】有时候我们需要调用block 的copy函数,将block拷贝到堆上。看下面的代码:
-(id) getBlockArray{
int val =10;
return [[NSArray alloc]initWithObjects:
^{NSLog(@"blk0:%d",val);},
^{NSLog(@"blk1:%d",val);},nil];
}
id obj = getBlockArray();
typedef void (^blk_t)(void);
blk_t blk = (blk_t){obj objectAtIndex:0};
blk();
这段代码在最后一行blk()会异常,因为数组中的block是栈上的。因为val是栈上的。解决办法就是调用copy方法。
【要点4】不管block配置在何处,用copy方法复制都不会引起任何问题。在ARC环境下,如果不确定是否要copy block尽管copy即可。ARC会打扫战场。
注意:在栈上调用copy那么复制到堆上,在全局block调用copy什么也不做,在堆上调用block 引用计数增加
本人用Xcode 5.1.1 iOS sdk 7.1 编译发现:并非《Objective-C》高级编程这本书中描述的那样,看下面代码
int val肯定是在栈上的,我保存了val的地址,看看block调用前后是否变化。输出一致说明是栈上,不一致说明是堆上。
typedef int (^blkt1)(void) ;
-(void) stackOrHeap{
__block int val =10;
int *valPtr = &val;//使用int的指针,来检测block到底在栈上,还是堆上
blkt1 s= ^{
NSLog(@"val_block = %d",++val);
return val;};
s();
NSLog(@"valPointer = %d",*valPtr);
}
在ARC下>>>>>>>>>>>该block被会直接生成到堆上了。看log: val_block = 11 valPointer = 10
在非ARC下>>>>>>>>>该block还是在栈上的。 看log:val_block = 11 valPointer = 11
调用copy之后的结果呢:
-(void) stackOrHeap{
__block int val =10;
int *valPtr = &val;//使用int的指针,来检测block到底在栈上,还是堆上
blkt1 s= ^{
NSLog(@"val_block = %d",++val);
return val;};
blkt1 h = [s copy];
h();
NSLog(@"valPointer = %d",*valPtr);
}
----------------在ARC下>>>>>>>>>>>无效果。 val_block = 11 valPointer = 10
----------------在非ARC下>>>>>>>>>确实复制到堆上了。 val_block = 11 valPointer = 10
用这个表格来表示
/*当block捕获了自动变量时候
------------------------------------------------------------------
| where block stay | ARC | 非ARC |
-------------------------------------------------------------------
| copy | heap | heap |
------------------------------------------------------------------
| no copy | heap | stack |
------------------------------------------------------------------
*/
block存储区域——如何验证block在栈上,还是堆上,布布扣,bubuko.com
block存储区域——如何验证block在栈上,还是堆上
标签:block实现 栈 堆
原文地址:http://blog.csdn.net/hherima/article/details/38620175