block内存篇
本文目的:对Block内存问题更加了解
概念理解:一种数据类型或比较特殊的对象,相当于一个指向函数的指针,该指针指向一段封装代码,调用block块代码好比调用该指针指向的函数代码
block分类:
- NSGlobalBlock:位于全局静态区。
- NSStackBlock:位于栈区,函数返回时被销毁
- NSMallocBlock:位于堆区,当引用计数为0时被销毁,由NSStackBlock从栈区copy到堆区
栈区(stack):由系统自动分配,一般存放函数参数值、局部变量的值等。由编译器自动创建与释放。其操作方式类似于数据结构中的栈,即后进先出、先进后出的原则
堆区(heap):一般由程序员申请并指明大小,最终也由程序员释放。如果程序员不释放,程序结束时可能会由OS回收。
全局区/静态区:顾名思义,全局变量和静态变量存储在这个区域。只不过初始化的全局变量和静态变量存储在一块,未初始化的全局变量和静态变量存储在一块。程序结束后由系统释放。
文字常量区:这个区域主要存储字符串常量。程序结束后由系统释放。
程序代码区:这个区域主要存放函数体的二进制代码
例子: int a = 0; // 全局初始化区 char *p1; // 全局未初始化区 main { int b; // 栈 char s[] = "abc"; // 栈 char *p2; // 栈 char *p3 = "123456"; // 123456\0在常量区,p3在栈上 static int c =0; // 全局静态初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); // 分配得来的10和20字节的区域就在堆区 strcpy(p1, "123456"); // 123456\0在常量区,这个函数的作用是将"123456" 这串字符串复制一份放在p1申请的10个字节的堆区域中。 // p3指向的"123456"与这里的"123456"可能会被编译器优化成一个地址。 }
block区分:
NSGlobalBlock:未引用外部任何变量即为NSGlobalBlock
NSStackBlock:引用外部变量,且只有一次执行,block返回后栈区将释放该block
NSMallocBlock:当需要多次执行时,就会把该block从栈中copy到堆中,以便多次执行
block-arc/mrc内存问题:
mrc下引用外部变量,则block是在栈区;arc下block默认生成于栈区,然后自动copy至堆区。
mrc环境:
1.当打印myBlock时发现mrc下对外部变量引用是在栈区,并没有进行copy至堆区
2.myBlock内部对外部变量stopName进行引用,执行block的时候内存计数器仍为1,证明retain失效,从而证明栈区无法release、retain,由系统自动分配和释放内存;
3.对myBlock进行copy,发现yourBlock是在堆区,stopName内存计数器+1
![]()
arc环境:
执行myBlock,发现是在堆区,证明arc环境下回自动将block从栈区copy至堆区
![]()
代码分享:内容包括定义、使用、循环引用、内存覆盖等问题例子
百度云:http://pan.baidu.com/s/1c1Y21hA
浙公网安备 33010602011771号