设为首页 加入收藏

TOP

block存储区域――如何验证block在栈上,还是堆上
2015-07-20 17:53:37 来源: 作者: 【 】 浏览:1
Tags: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 | ------------------------------------------------------------------
*/ 详细内容见 点击打开链接
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇POJ 3090 Visible Lattice Points 下一篇UVA654- Ratio(暴力枚举)

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容: