先看如下代码
注以下代码均为mrc环境下运行
// // main.m // Block2 // // Created by xufan on 16/8/13. // Copyright © 2016年 xufan. All rights reserved. // #import <Foundation/Foundation.h> typedef void(^blk)(void); typedef void(^blk1)(void); blk g_blk; blk1 g_blk1; void test1() { blk blkimp = ^{ printf("test1\n"); }; blkimp(); g_blk = blkimp; } void test2() { int a = 10; blk1 blkimp = ^{ printf("test2 a = %d\n",a); }; blkimp(); g_blk1 = blkimp; } int main(int argc, const char * argv[]) { test1(); test2(); // g_blk(); // g_blk1(); return 0; }
主函数最后两句,去掉注释,执行正常,注释去掉,再来执行,程序退出,退出代码为120,我们再随便定义一个函数像这样
void test3() { int a = 20; printf("a = %d",a); } 分别在g_blk(), 和g_blk1()调用之前调用这个函数,结果直接崩溃,如果你对函数调用压栈过程比较清楚应该就明白了
第一个g_blk执行不奔溃是因为它本身生成的位置在数据区,也可以说是全局区,在任何地方都可以正常访问,第二个g_blk1生成在栈上,test2函数执行完成后,这块区域已经被回收了,但是其数据还没有被破坏,全局指针还保留了原有地址,当我们在这之间任意调用函数,并且栈上生成一些变量后,之前block结构体的数据结构被破坏,全局指针继续访问,程序崩溃...
block位置在栈区还是在堆区,打印其地址,就知道了,另外__block_impl结构体里面第一个参数是void *isa指针,由此可知block可以转换为一个oc对象