p 0x02000000 & 0x00000000c1000002 ,即BLOCK_HAS_COPY_DISPOSE & flags ,等于0,表示没有Block_descriptor_2;
判断是否有Block_descriptor_3:
p/x 1<<30,即1左移30位;
p 0x40000000 & 0x00000000c1000002 ,即BLOCK_HAS_SIGNATURE & flags ,如果有值则说明有Block_descriptor_3;
p (char *)0x000000010039b390:获取Block_descriptor_3中的属性signature签名;
(lldb) p/x 1<<30(int) $5=0x40000000(lldb) p 0x40000000&0x00000000c1000002(unsignedint) $6=1073741824(lldb) p (char*)0x000000010039b390(char*) $8=0x000000010039b390"v8@?0"
po [NSMethodSignature signatureWithObjCTypes:“v8@?0”] ,即打印签名;
(lldb) p (char*)0x000000010039b390(char*) $8=0x000000010039b390"v8@?0"(lldb) po [NSMethodSignature signatureWithObjCTypes:"v8@?0"]<NSMethodSignature:0xb56f60fe49be8c07>
number of arguments =1
frame size =224
is special structreturn? NO
return value:--------------------------------
type encoding (v)'v'
flags {
}
modifiers {
}
frame {
offset =0, offset adjust =0, size =0, size adjust =0}
memory {
offset =0, size =0}
argument 0:--------------------------------// encoding = (@),类型是 @?
type encoding (@)'@?'// @是isObject ,?是isBlock,代表 isBlockObject
flags {
isObject, isBlock}
modifiers {
}
frame {
offset =0, offset adjust =0, size =8, size adjust =0}// 所在偏移位置是8字节
memory {
offset =0, size =8}
// Copy, or bump refcount, of a block. If really copying, call the copy helper if present.// block的拷贝操作: 栈Block -> 堆Blockvoid*_Block_copy(constvoid*arg){
struct Block_layout *aBlock;if(!arg)returnNULL;// The following would be better done as a switch statement
aBlock =(struct Block_layout *)arg;// 强转为Block_layout类型对象,防止对外界造成影响if(aBlock->flags & BLOCK_NEEDS_FREE){
// 是否需要释放// latches on highlatching_incr_int(&aBlock->flags);return aBlock;}elseif(aBlock->flags & BLOCK_IS_GLOBAL){
// 如果是全局block,直接返回return aBlock;}else{
// 为栈block 或者 堆block,由于堆区需要申请内存,所以只可能是栈区// Its a stack block. Make a copy. 它是一个堆栈块block拷贝。struct Block_layout *result =(struct Block_layout *)malloc(aBlock->descriptor->size);//申请空间并接收if(!result)returnNULL;//通过memmove内存拷贝,将 aBlock 拷贝至resultmemmove(result, aBlock, aBlock->descriptor->size);// bitcopy first#if __has_feature(ptrauth_calls)// Resign the invoke pointer as it uses address authentication.
result->invoke = aBlock->invoke;//可以直接调起invoke#endif// reset refcount
result->flags &=~(BLOCK_REFCOUNT_MASK|BLOCK_DEALLOCATING);// XXX not needed 告知可释放
result->flags |= BLOCK_NEEDS_FREE |2;// logical refcount 1_Block_call_copy_helper(result, aBlock);// Set isa last so memory analysis tools see a fully-initialized object.
result->isa = _NSConcreteMallocBlock;//设置block对象类型为堆区blockreturn result;}}
// Block 捕获的外界变量的种类// Runtime support functions used by compiler when generating copy/dispose helpers// Values for _Block_object_assign() and _Block_object_dispose() parametersenum{
// see function implementation for a more complete description of these fields and combinations// 普通对象,即没有其他的引用类型
BLOCK_FIELD_IS_OBJECT =3,// id, NSObject, __attribute__((NSObject)), block, ...// block类型作为变量
BLOCK_FIELD_IS_BLOCK =7,// a block variable// 经过__block修饰的变量
BLOCK_FIELD_IS_BYREF =8,// the on stack structure holding the __block variable// weak 弱引用变量
BLOCK_FIELD_IS_WEAK =16,// declared __weak, only used in byref copy helpers// 返回的调用对象 - 处理block_byref内部对象内存会加的一个额外标记,配合flags一起使用
BLOCK_BYREF_CALLER =128,// called from __block (byref) copy/dispose support routines.};
// When Blocks or Block_byrefs hold objects their destroy helper routines call this entry point// to help dispose of the contents 当Blocks或Block_byrefs持有对象时,其销毁助手例程将调用此入口点以帮助处置内容void_Block_object_dispose(constvoid*object,constint flags){
switch(os_assumes(flags & BLOCK_ALL_COPY_DISPOSE_FLAGS)){
case BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK:case BLOCK_FIELD_IS_BYREF://__block修饰的变量,即bref类型的
// get rid of the __block data structure held in a Block_Block_byref_release(object);break;case BLOCK_FIELD_IS_BLOCK://block类型的变量
_Block_release(object);break;case BLOCK_FIELD_IS_OBJECT://普通对象
_Block_release_object(object);break;case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT:case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK:case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK:case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK | BLOCK_FIELD_IS_WEAK:break;default:break;}}
进入_Block_byref_release源码,主要就是对象、变量的释放销毁:
staticvoid_Block_byref_release(constvoid*arg){
//对象强转为Block_byref类型结构体struct Block_byref *byref =(struct Block_byref *)arg;// dereference the forwarding pointer since the compiler isn't doing this anymore (ever?)
byref = byref->forwarding;//取消指针引用if(byref->flags & BLOCK_BYREF_NEEDS_FREE){
int32_t refcount = byref->flags & BLOCK_REFCOUNT_MASK;os_assert(refcount);if(latching_decr_int_should_deallocate(&byref->flags)){
if(byref->flags & BLOCK_BYREF_HAS_COPY_DISPOSE){
//是否有拷贝辅助函数struct Block_byref_2 *byref2 =(struct Block_byref_2 *)(byref+1);(*byref2->byref_destroy)(byref);//销毁拷贝对象}free(byref);//释放}}}