block测试题目验证结果

来源:互联网 发布:中文版国际象棋软件 编辑:程序博客网 时间:2024/06/07 14:23


以下是网上流传的5个block的测试题目,写代码测试了一下。为了更详细的看到block分配在哪里,对代码做了修改。不知是否会违反代码的本意,请大家指点。
block能否运行取决于block是否被copy到了堆上,如果在堆上或全局数据区就一定能运行。在网上看到一个断言,ARC使能后不再有NSStackBlock,基于这句断言,ARC使能的情况下,block的使用无论如何都不会有问题。
ARC使能
1 不使用自动变量,block位于__NSGlobalBlock__
2 其他情况,block位于__NSMallocBlock__
ARC禁用
1 不使用自动变量,block位于__NSGlobalBlock__
2 使用自动变量,block位于__NSStackBlock__
3 作为函数返回值,block位于__NSStackBlock__

#import <Foundation/Foundation.h>void exampleA(){/*ARC设置无关,都可以正常运行*/char a = 'A';void (^blk)(void) =^(void){printf("%c\n", a);};/*ARC使能,block是__NSMallocBlock__ARC禁用,block是__NSStackBlock__*/NSLog(@"%s %@", __FUNCTION__, blk);blk();}void exampleB_addBlockToArray(NSMutableArray *array){char b = 'B';void (^blk)(void) = ^(void){printf("%c\n", b);    };/*ARC使能,block是__NSMallocBlock__ARC禁用,block是__NSStackBlock__*/NSLog(@"%s %@", __FUNCTION__, blk);[array addObject: blk];}void exampleB(){/*ARC使能正常,ARC禁用crash*/NSMutableArray *array = [NSMutableArray array];exampleB_addBlockToArray(array);void (^blk)(void) = [array objectAtIndex: 0];NSLog(@"%s %@", __FUNCTION__, blk);blk();}void exampleC_addBlockToArray(NSMutableArray *array){void (^blk)(void) = ^(void){printf("C\n");};/*ARC使能,block是__NSGlobalBlock__ARC禁用,block是__NSGlobalBlock__没有使用自动变量,所以编译器把block放到__NSGlobalBlock__区域*/    NSLog(@"%s %@", __FUNCTION__, blk);[array addObject: blk];}void exampleC(){/*ARC设置无关,都可以正常运行*/NSMutableArray *array = [NSMutableArray array];exampleC_addBlockToArray(array);void (^blk)(void) = [array objectAtIndex: 0];NSLog(@"%s %@", __FUNCTION__, blk);blk();}void (^exampleD_getBlock())(void){char d = 'D';void (^blk)(void) = ^(void){printf("%c\n", d);};/*ARC使能时,block是__NSMallocBlock__ARC禁用时,block是__NSStackBlock__使用自动变量,所以编译器把block放到__NSStackBlock__区域*/    NSLog(@"%s %@", __FUNCTION__, blk);return blk;}void exampleD(){/*ARC使能正常,ARC禁用crash*/void (^blk)(void) = exampleD_getBlock();NSLog(@"%s %@", __FUNCTION__, blk);blk();}void (^exampleE_getBlock())(void){char e = 'E';void (^blk)(void) =^(void){printf("%c\n", e);};NSLog(@"%s %@", __FUNCTION__, blk);return blk;}void exampleE(){/*和D完全一样,原来的测试代码也是同一个意思吗?*/void (^blk)(void) = exampleE_getBlock();    NSLog(@"%s %@", __FUNCTION__, blk);blk();}int main(const int argc, const char *argv[]){@autoreleasepool {exampleA(); /*ARC使能 OK ARC禁用OK*/exampleB(); /*ARC使能 OK ARC禁用NG*/exampleC(); /*ARC使能 OK ARC禁用OK*/exampleD(); /*ARC使能 OK ARC禁用NG*/exampleE(); /*ARC使能 OK ARC禁用NG*/    }return 0;}


ARC使能的结果
2015-03-05 10:37:29.368 cpro[462:7228] exampleA <__NSMallocBlock__: 0x100206880>
A
2015-03-05 10:37:29.370 cpro[462:7228] exampleB_addBlockToArray <__NSMallocBlock__: 0x100300790>
2015-03-05 10:37:29.370 cpro[462:7228] exampleB <__NSMallocBlock__: 0x100300790>
B
2015-03-05 10:37:29.371 cpro[462:7228] exampleC_addBlockToArray <__NSGlobalBlock__: 0x1000020d0>
2015-03-05 10:37:29.371 cpro[462:7228] exampleC <__NSGlobalBlock__: 0x1000020d0>
C
2015-03-05 10:37:29.371 cpro[462:7228] exampleD_getBlock <__NSMallocBlock__: 0x1003009e0>
2015-03-05 10:37:29.371 cpro[462:7228] exampleD <__NSMallocBlock__: 0x1003009e0>
D
2015-03-05 10:37:29.371 cpro[462:7228] exampleE_getBlock <__NSMallocBlock__: 0x1003009e0>
2015-03-05 10:37:29.371 cpro[462:7228] exampleE <__NSMallocBlock__: 0x1003009e0>
E


ARC禁止的结果
2015-03-05 10:39:58.392 cpro[475:7854] exampleA <__NSStackBlock__: 0x7fff5fbff7f8>
A
2015-03-05 10:39:58.394 cpro[475:7854] exampleB_addBlockToArray <__NSStackBlock__: 0x7fff5fbff7c0>
注释掉exampleB后继续
2015-03-05 10:52:05.545 cpro[491:9428] exampleC_addBlockToArray <__NSGlobalBlock__: 0x1000010a0>
2015-03-05 10:52:05.546 cpro[491:9428] exampleC <__NSGlobalBlock__: 0x1000010a0>
C
2015-03-05 10:52:05.546 cpro[491:9428] exampleD_getBlock <__NSStackBlock__: 0x7fff5fbff7d8>
2015-03-05 10:52:05.546 cpro[491:9428] exampleD <__NSStackBlock__: 0x7fff5fbff7d8>


0 0