此函数声明和相关的结构体如下
void Block_copy(struct block_literal_generic block);
struct block_literal_generic {
void *isa; // 可能为NSGlobalBlock,NSStackBlock,NSMallocBlock
int flags; // 内存块属性,决定了Block_copy的行为,
int reserved; // 网上说是是当前block引用计数
void (*invoke)(void *, ...); // block函数地址
struct Block_descriptor {
unsigned long int reserved;
unsigned long int size; // _block_literal_generic占用大小
void (*copy_helper)(void *dst, void *src); // 对引用的变量进行retain或copy操作
void (*dispose_helper)(void *src);
} descriptor;
// 紧挨着存放所有被引用的局部变量,格式下面说明
};
struct _block_byref_mydata
{
uint_8* a; // 总是0
_block_byref_mydata* b; // 总是指向该结构体,用途不明
unsigned long c;
unsigned long d; //猜测是__block mask
__block_byref_id_object_copy e; //用来拷贝__block变量的函数
__block_byref_id_object_release f; // 释放__block变量的函数
NSObject* g; //指向原__block变量的地址
};
Block类型
Block的初始类型可能是NSGlobalBlock,也可能是NSStackBlock
当block内部没有引用到包含Block的最小范围的栈变量时候,则是NSGlobalBlock,否则为NSStackBlock
调用Block_copy可以从NSStackBlock生成NSMallocBlock,对NSGlobalBlock调用Block_copy返回NSGlobalBlock本身。
变量的存储
局部变量类型可能有,Objective-C类型,简单类型如int, int*, 结构体,C++类,以及上面各个类型经过__block修饰的变量类型。
1. Objective-C类型:存储Objective-C指针本身
2. a.简单类型:存储变量的值,例如int i = 9;存储的是0x00000009,占用4字节,
b.结构体类型:存储结构体的内容,,例如结构体struct{short i=20, short j=100},存储的是0x00640014,占用空间为8
c.C++类:存储经过拷贝构造函数生成的新对象内存,如果存在虚表,也写入内存,占用空间和sizeof(class)一致的.
3.__block修饰的变量:指向_block_byref_mydata结构体的指针,当变量经过__block修饰之后,会生成_block_byref_mydata结构体,同时把指针放入block变量中,占用4字节
如何对变量进行retain操作
因为descriptor.copy_helper函数是编译器根据当前有多少个引用了的变量和变量存储未知动态生成的,所以可以很好的规定哪些地址是需要retain的,哪些是简单类型只需要拷贝内容的,哪些是__block修辞的变量需要特殊操作的。
参考:http://www.cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html