clang -rewrite-objc main.m
若是Xcode版本較高,可能會出現報錯:html
./block_VC.h:9:9: fatal error: 'UIKit/UIKit.h' file not found
此時可嘗試另外一個命令:objective-c
clang -x objective-c -rewrite-objc -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk main.m
Block的基本概念express
1.沒有捕獲任何局部變量的block爲_NSConcreteGlobalBlock,它以static函數的形式存儲在代碼區app
2.捕獲了局部變量的block爲_NSConcreteStackBlock框架
3.當_NSConcreteStackBlock出現上面四種狀況時,會變成_NSConcreteMallocBlock。(注意此時是調用了Block_Copy函數後)函數
Block編譯後結果分析佈局
基本類型變量spa
OC源碼:3d
NSInteger age = 10; void(^completeBlock)(NSString *) = ^(NSString *name) { NSString *info = [NSString stringWithFormat:@"name:%@ - age:%d",name,age]; NSLog(@"%@",info); }; completeBlock(@"jack");
編譯後的C\C++源碼:指針
// __block_impl爲block的基礎struct //1.*isa:當前block對象所屬的類型(注意:在OC語言中帶有isa指針的都是對象) //2.Flags:標示位,當類型爲NSConcreteMallocBlock時,表示須要ARC內存管理,其餘默認不須要內存管理 //3.Reserved:預留標示位,暫時無論它 //4.block的實際static內部函數地址指針 struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; // __main_block_impl_0爲block的最終struct //1.impl:爲上面的__block_impl結構體實例 //2.Desc:爲block的描述結構體__main_block_desc_0,裏面包含了block結構體的信息描述,在下面講解 //3.age:從外面補貨的變量,block採用的方式是直接在block實例中定義一個變量,將捕獲的值賦給它 //4.__main_block_impl_0:爲block結構體的構造函數,參數中包含從外面捕獲的變量值 struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; NSInteger age; __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSInteger _age, int flags=0) : age(_age) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; //__main_block_func_0爲block具體實現的函數載體,具體的block的任務實如今此函數內 //參數:1是block的實例指針,2是block的外部傳參name static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) { //從block實例中獲取age變量的值 NSInteger age = __cself->age; // bound by copy //生成字符串NSString *info = [NSString stringWithFormat:@"name:%@ - age:%d",name,age]; NSString *info = ((NSString * _Nonnull (*)(id, SEL, NSString * _Nonnull, ...))(void *)objc_msgSend)((id)objc_getClass("NSString"), sel_registerName("stringWithFormat:"), (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_83d55e_mi_0, (NSString *)name, (NSInteger)age); //打印NSLog(@"%@",info); NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_83d55e_mi_1,info); } //reserved:保留字0 //Block_size:block實例在內存中佔據內存大小 //__main_block_desc_0_DATA:默認desc結構體實例 static struct __main_block_desc_0 { size_t reserved; size_t Block_size; } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0)}; //main函數 int main(int argc, char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; NSInteger age = 10; void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, age)); ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_83d55e_mi_2); return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")))); } }
block簡單結構佈局
struct __block_impl struct __main_block_impl_0 static void __main_block_func_0 static struct __main_block_desc_0
__block NSInteger age = 10; void(^completeBlock)(NSString *) = ^(NSString *name) { NSString *info = [NSString stringWithFormat:@"name:%@ - age:%d",name,age]; NSLog(@"%@",info); }; completeBlock(@"jack");
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; //age的block變量實例__Block_byref_age //__isa:age的block變量實例所屬的類型 //__forwarding:age的block變量實例的指針 //__flags:變量是否被內存管理標示 //__size:所佔內存大小 //age:age變量值 struct __Block_byref_age_0 { void *__isa; __Block_byref_age_0 *__forwarding; int __flags; int __size; NSInteger age; }; //原來的age變量值,變成了__Block_byref_age_0變量指針 struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_age_0 *age; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_age_0 *_age, int flags=0) : age(_age->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) { //經過block實例獲取變量的指針 __Block_byref_age_0 *age = __cself->age; // bound by ref NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_7acc63_mi_0,name,(age->__forwarding->age)); } //當block從棧複製到堆上時,會對__Block_byref_age_0變量進行拷貝,也會從棧拷貝到堆上 static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->age, (void*)src->age, 8/*BLOCK_FIELD_IS_BYREF*/);} //__Block_byref_age_0變量的析構函數,當block實例的引用計數爲0時,是否__Block_byref_age_0變量的內存空間 static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->age, 8/*BLOCK_FIELD_IS_BYREF*/);} //desc結構體中新增了copy函數和dispose函數指針 static struct __main_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*); void (*dispose)(struct __main_block_impl_0*); } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0}; int main(int argc, char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; //block變量實例 __attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*)0,(__Block_byref_age_0 *)&age, 0, sizeof(__Block_byref_age_0), 10}; //block實例 void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_age_0 *)&age, 570425344)); ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_7acc63_mi_1); return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")))); } }
簡單結構佈局
struct __block_impl struct __main_block_impl_0 static void __main_block_func_0 static struct __main_block_desc_0 //新增 struct __Block_byref_age_0 static void __main_block_copy_0( static void __main_block_dispose_0(
__block NSInteger age = 10;後,在簡單佈局結構中新增了3項
struct __Block_byref_age_0 static void __main_block_copy_0( static void __main_block_dispose_0(
OC源碼:
NSMutableArray *friends = [NSMutableArray array];; void(^completeBlock)(NSString *) = ^(NSString *name) { NSLog(@"%@--%@",name,friends); }; completeBlock(@"jack");
編譯後的C\C++源碼:
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; NSMutableArray *friends; __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSMutableArray *_friends, int flags=0) : friends(_friends) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) { NSMutableArray *friends = __cself->friends; // bound by copy NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_1b4a2f_mi_0,name,friends); } //block實例從棧複製到堆上時,將指針變量引用計數加一 static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->friends, (void*)src->friends, 3/*BLOCK_FIELD_IS_OBJECT*/);} //block實例引用計數爲0時,析構指針變量對象 static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->friends, 3/*BLOCK_FIELD_IS_OBJECT*/);} static struct __main_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*); void (*dispose)(struct __main_block_impl_0*); } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0}; int main(int argc, char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; NSMutableArray *friends = ((NSMutableArray * _Nonnull (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("array"));; void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, friends, 570425344)); ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_1b4a2f_mi_1); return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")))); } }
簡單結構佈局
struct __block_impl struct __main_block_impl_0 static void __main_block_func_0 static struct __main_block_desc_0 static void __main_block_copy_0( static void __main_block_dispose_0(
__block指針類型變量
OC源碼:
__block NSMutableArray *friends = [NSMutableArray array];; void(^completeBlock)(NSString *) = ^(NSString *name) { NSLog(@"%@--%@",name,friends); }; completeBlock(@"jack");
編譯後的C\C++源碼:
struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; //__Block_byref_friends_0結構體實例中包含了friends指針 //而且多了__Block_byref_id_object_copy函數:對friends進行copy //多了__Block_byref_id_object_dispose函數:對friends進行析構 struct __Block_byref_friends_0 { void *__isa; __Block_byref_friends_0 *__forwarding; int __flags; int __size; void (*__Block_byref_id_object_copy)(void*, void*); void (*__Block_byref_id_object_dispose)(void*); NSMutableArray *friends; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_friends_0 *friends; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_friends_0 *_friends, int flags=0) : friends(_friends->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } }; static void __main_block_func_0(struct __main_block_impl_0 *__cself, NSString *name) { __Block_byref_friends_0 *friends = __cself->friends; // bound by ref NSLog((NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_252d0c_mi_0,name,(friends->__forwarding->friends)); } //block實例從棧複製到堆上時,__block變量結構體實例將指針變量引用計數加一,同時__block變量結構體實例內的NSMutableArray *friends變量也遞歸加一 static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->friends, (void*)src->friends, 8/*BLOCK_FIELD_IS_BYREF*/);} //block實例引用計數爲0時,__block變量結構體實例被析構,同時__block變量結構體實例內的NSMutableArray *friends變量也遞歸析構 static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->friends, 8/*BLOCK_FIELD_IS_BYREF*/);} static struct __main_block_desc_0 { size_t reserved; size_t Block_size; void (*copy)(struct __main_block_impl_0*, struct __main_block_impl_0*); void (*dispose)(struct __main_block_impl_0*); } __main_block_desc_0_DATA = { 0, sizeof(struct __main_block_impl_0), __main_block_copy_0, __main_block_dispose_0}; int main(int argc, char * argv[]) { /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; __attribute__((__blocks__(byref))) __Block_byref_friends_0 friends = {(void*)0,(__Block_byref_friends_0 *)&friends, 33554432, sizeof(__Block_byref_friends_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((NSMutableArray * _Nonnull (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("array"))};; void(*completeBlock)(NSString *) = ((void (*)(NSString *))&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_friends_0 *)&friends, 570425344)); ((void (*)(__block_impl *, NSString *))((__block_impl *)completeBlock)->FuncPtr)((__block_impl *)completeBlock, (NSString *)&__NSConstantStringImpl__var_folders_4y_ks8945f50k51_0j95ytw7ss80000gn_T_main_252d0c_mi_1); return UIApplicationMain(argc, argv, __null, NSStringFromClass(((Class (*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("AppDelegate"), sel_registerName("class")))); } }
簡單結構變量
struct __block_impl struct __main_block_impl_0 static void __main_block_func_0 static struct __main_block_desc_0 static void __main_block_copy_0( static void __main_block_dispose_0( //新增 struct __Block_byref_age_0
//局部變量 __block NSMutableArray *friends = [NSMutableArray array];; void(^completeBlock)(NSString *) = ^(NSString *name) { NSLog(@"%@--%@",name,friends); }; (lldb) expression -P 5 -- completeBlock (void (^)(NSString *)) $2 = 0x000000010a061130 { __isa = __NSMallocBlock__ __flags = -1023410170 __reserved = 0 __FuncPtr = 0x000000010a061130 (iOS_KnowledgeStructure`__main_block_invoke at main.m:19) {} }
利用clang轉換後的C\C++源碼
struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_friends_0 *friends; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_friends_0 *_friends, int flags=0) : friends(_friends->__forwarding) { impl.isa = &_NSConcreteStackBlock; impl.Flags = flags; impl.FuncPtr = fp; Desc = desc; } };
static void *_Block_copy_internal(const void *arg, const int flags) { struct Block_layout *aBlock; const bool wantsOne = (WANTS_ONE & flags) == WANTS_ONE; // 1 if (!arg) return NULL; // 2 aBlock = (struct Block_layout *)arg; // 3 if (aBlock->flags & BLOCK_NEEDS_FREE) { // latches on high latching_incr_int(&aBlock->flags); return aBlock; } // 4 else if (aBlock->flags & BLOCK_IS_GLOBAL) { return aBlock; } // 5 struct Block_layout *result = malloc(aBlock->descriptor->size); if (!result) return (void *)0; // 6 memmove(result, aBlock, aBlock->descriptor->size); // bitcopy first // 7 result->flags &= ~(BLOCK_REFCOUNT_MASK); // XXX not needed result->flags |= BLOCK_NEEDS_FREE | 1; // 8 result->isa = _NSConcreteMallocBlock; // 9 if (result->flags & BLOCK_HAS_COPY_DISPOSE) { (*aBlock->descriptor->copy)(result, aBlock); // do fixup } return result; }