类型分为:
_NSConcreteGlobalBlock(全局块)
_NSConcreteStackBlock(栈块)
_NSConcreteMallocBlock(堆块)
栈区(stack):由系统自动分配,一般存放函数参数值、局部变量的值等。由编译器自动创建与释放。其操作方式类似于数据结构中的栈,即后进先出、先进后出的原则。
例如:在函数中申明一个局部变量int b;系统自动在栈中为b开辟空间。
堆区(heap):一般由程序员申请并指明大小,最终也由程序员释放。如果程序员不释放,程序结束时可能会由OS回收。对于堆区的管理是采用链表式管理的,操作系统有一个记录空闲内存地址的链表,当接收到程序分配内存的申请时,操作系统就会遍历该链表,遍历到一个记录的内存地址大于申请内存的链表节点,并将该节点从该链表中删除,然后将该节点记录的内存地址分配给程序。
分别举3个列子
typedef void (^blk_t) ();
int main(int argc, const char * argv[]) {
blk_t block = ^{
printf("I'm just a block\n");
};
block();
return 0;
}
这种是 _NSConcreteGlobalBlock 全局
typedef void (^blk_t) ();
int main(int argc, const char * argv[]) {
int i = 1;
blk_t block = ^{
printf("%d\n",i);
};
block();
return 0;
}
这种 是 堆块
typedef void (^blk_t) ();
int main(int argc, const char * argv[]) {
int i = 1;
__weak blk_t block = ^{
printf("%d\n",i);
};
block();
return 0;
}
这种是 栈块
总结如下:
记述全局变量的地方创建的Block,这种是全局的
不截获自动变量的时候将会被编译器编译为_NSConcreteGlobalBlock.
进行了copy操作(实质上是调用_Block_copy函数),会让块从栈复制到堆上.
调用Block的copy实例方法,会把栈上的block复制到堆上.
将Block赋值给附有__strong修饰符id类型的类或Block类型成员变量时是在堆上的
Block作为函数返回值时是在堆上
Block的copy,retain,release操作
对block retain操作并不会改变引用计数器,retainCount ,始终为1
NSGlobalBlock:retain、copy、release操作都无效;
Block_copy与copy等效,Block_release与release等效
NSStackBlock:retain、release操作无效,必须注意的是,NSStackBlock在函数返回后,Block内存将被回收。即使retain也没用。容易犯的 错误是[[mutableAarry addObject:stackBlock],在函数出栈后,从mutableAarry中取到的stackBlock已经被回收,变成了野指针。正确的做法是先将stackBlock copy到堆上,然后加入数组:[mutableAarry addObject:[[stackBlock copy] autorelease]]。支持copy,copy之后生成新的NSMallocBlock类型对象。
NSMallocBlock支持retain、release,虽然retainCount始终是1,但内存管理器中仍然会增加、减少计数。copy之后不会生成新的对象,只是增加了一次引用,类似retain
尽量不要对Block使用retain操作
网友评论