iOS block 再次探秘 && AutoreleasePool

stack、malloc、global block区分

block分类,先后区分逻辑是gloabal、stack、malloc
注意:global:void (^stackBlock)() = ^{}; clang是stack
malloc:block为strong类型,且捕获了外部变量时。clang是stack
这两种类型用clang看都是stack,但其实分别是global和malloc。有人(唐巧)说这是clang和llvm编译方式不一样,待验证,期待更好的解释。我猜测也是的,你能看到copy 的调用吗,看不到,我猜clang只会给你大概的一点。

__block 之于数组

  • 加不加block都行,推荐不加
  • 加了只是里面多了一个结构体,然后发现还是往哪个结构体里面的arr发消息,不加就是直接给arr发消息
#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
    @autoreleasepool {
         NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1",@"2",@"3", nil];
        void(^block)(void) = ^{
            [arr addObject:@"4"];
        };
        block();
    }
}

clang -rewrite-objc main.m 后

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  NSMutableArray *arr;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSMutableArray *_arr, int flags=0) : arr(_arr) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  NSMutableArray *arr = __cself->arr; // bound by copy //

            ((void (*)(id, SEL, ObjectType _Nonnull))(void *)objc_msgSend)((id)arr, sel_registerName("addObject:"), (id _Nonnull)(NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_af0c47_mi_3);
        }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->arr, (void*)src->arr, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->arr, 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 *arr = ((NSMutableArray * _Nonnull (*)(id, SEL, ObjectType _Nonnull, ...))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("arrayWithObjects:"), (id _Nonnull)(NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_af0c47_mi_0, (NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_af0c47_mi_1, (NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_af0c47_mi_2, __null);
        void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, arr, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

a r r b l o c k \color{red}{注意这里arr也是指针,外面不能赋值的原因,如果赋值了你只改变了block里面的值,}
\color{red}{并没有改变外面的值}

#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
    @autoreleasepool {
        __block NSMutableArray *arr = [NSMutableArray arrayWithObjects:@"1",@"2",@"3", nil];
        void(^block)(void) = ^{
            [arr addObject:@"4"];
        };
        block();
    }
}

clang -rewrite-objc main.m 后


struct __Block_byref_arr_0 {
  void *__isa;
__Block_byref_arr_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 NSMutableArray *arr;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_arr_0 *arr; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_arr_0 *_arr, int flags=0) : arr(_arr->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_arr_0 *arr = __cself->arr; // bound by ref
            ((void (*)(id, SEL, ObjectType _Nonnull))(void *)objc_msgSend)((id)(arr->__forwarding->arr), sel_registerName("addObject:"), (id _Nonnull)(NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_c4a3eb_mi_3);
        }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->arr, (void*)src->arr, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->arr, 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_arr_0 arr = {(void*)0,(__Block_byref_arr_0 *)&arr, 33554432, sizeof(__Block_byref_arr_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((NSMutableArray * _Nonnull (*)(id, SEL, ObjectType _Nonnull, ...))(void *)objc_msgSend)((id)objc_getClass("NSMutableArray"), sel_registerName("arrayWithObjects:"), (id _Nonnull)(NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_c4a3eb_mi_0, (NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_c4a3eb_mi_1, (NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_c4a3eb_mi_2, __null)};
        void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_arr_0 *)&arr, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
    

a r r = n i l 线 b l o c k a r r \color{red}{为什么这里就能在更改设置arr = nil ,下划线block 添加后,arr里面和外面是一个指针} \color{red}{也不是,这句话表述有问题,内外指针有关联,但不是一个指针,指向的内容相同}

block 之于常用变量

#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSInteger i = 1;
        void(^block)(void) = ^{
            NSLog(@"print i value %d",i);
        };
        block();
    }
}

//simpel:

   struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  NSInteger i;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSInteger _i, int flags=0) : i(_i) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  NSInteger i = __cself->i; // bound by copy

            NSLog((NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_ac2ab8_mi_0,i);
        }

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)};
int main(int argc, char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        NSInteger i = 1;
        void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, i));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
    @autoreleasepool {
       __block NSInteger i = 1;
        void(^block)(void) = ^{
            NSLog(@"print i value %d",i);
        };
        block();
    }
}

///复杂的

struct __Block_byref_i_0 {
  void *__isa;
__Block_byref_i_0 *__forwarding;
 int __flags;
 int __size;
 NSInteger i;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_i_0 *i; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_i_0 *_i, int flags=0) : i(_i->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_i_0 *i = __cself->i; // bound by ref

            NSLog((NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_d33923_mi_0,(i->__forwarding->i));
        }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->i, (void*)src->i, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->i, 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_i_0 i = {(void*)0,(__Block_byref_i_0 *)&i, 0, sizeof(__Block_byref_i_0), 1};
        void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_i_0 *)&i, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

block之于普通对象NSObject

加了关键字__block

#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
    @autoreleasepool {
       __block  NSObject *object = [[NSObject alloc] init];
        void(^block)(void) = ^{
            NSLog(@"print %@",object);
        };
        block();
    }
}

struct __Block_byref_object_0 {
  void *__isa;
__Block_byref_object_0 *__forwarding;
 int __flags;
 int __size;
 void (*__Block_byref_id_object_copy)(void*, void*);
 void (*__Block_byref_id_object_dispose)(void*);
 NSObject *object;
};

struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  __Block_byref_object_0 *object; // by ref
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_object_0 *_object, int flags=0) : object(_object->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  __Block_byref_object_0 *object = __cself->object; // bound by ref

            NSLog((NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_602bf3_mi_0,(object->__forwarding->object));
        }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->object, (void*)src->object, 8/*BLOCK_FIELD_IS_BYREF*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->object, 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_object_0 object = {(void*)0,(__Block_byref_object_0 *)&object, 33554432, sizeof(__Block_byref_object_0), __Block_byref_id_object_copy_131, __Block_byref_id_object_dispose_131, ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"))};
        void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, (__Block_byref_object_0 *)&object, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };
#import <Foundation/Foundation.h>
int main(int argc, char * argv[]) {
    @autoreleasepool {
         NSObject *object = [[NSObject alloc] init];
        void(^block)(void) = ^{
            NSLog(@"print %@",object);
        };
        block();
    }
}
//old
struct __main_block_impl_0 {
  struct __block_impl impl;
  struct __main_block_desc_0* Desc;
  NSObject *object;
  __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, NSObject *_object, int flags=0) : object(_object) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};
static void __main_block_func_0(struct __main_block_impl_0 *__cself) {
  NSObject *object = __cself->object; // bound by copy

            NSLog((NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_81d78e_mi_0,object);
        }
static void __main_block_copy_0(struct __main_block_impl_0*dst, struct __main_block_impl_0*src) {_Block_object_assign((void*)&dst->object, (void*)src->object, 3/*BLOCK_FIELD_IS_OBJECT*/);}

static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_object_dispose((void*)src->object, 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; 
        NSObject *object = ((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)((NSObject *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("NSObject"), sel_registerName("alloc")), sel_registerName("init"));
        void(*block)(void) = ((void (*)())&__main_block_impl_0((void *)__main_block_func_0, &__main_block_desc_0_DATA, object, 570425344));
        ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
    }
}
static struct IMAGE_INFO { unsigned version; unsigned flag; } _OBJC_IMAGE_INFO = { 0, 2 };

笔记

1、这里值得说明的一点是,如果Block外面还有很多自动变量,静态变量,等等,这些变量在Block里面并不会被使用到。那么这些变量并不会被Block捕获进来,也就是说并不会在构造函数里面传入它们的值。
Block捕获外部变量仅仅只捕获Block闭包里面会用到的值,其他用不到的值,它并不会去捕获。
2、我们可以发现,系统自动给我们加上的注释,bound by copy,自动变量val虽然被捕获进来了,但是是用 __cself->val来访问的。Block仅仅捕获了val的值,并没有捕获val的内存地址。所以在__main_block_func_0这个函数中即使我们重写这个自动变量val的值,依旧没法去改变Block外面自动变量val的值。
因为修改里面的值变成了修改里面局部变量值而已了
3、Block捕获的外部变量可以改变值的是静态变量,静态全局变量,全局变量。上面例子也都证明过了。
4、总结一下在Block中改变变量值有2种方式,一是传递内存地址指针到Block中,二是改变存储区方式(__block)。
NSMutableArray *arr ,NSObject *objc ,NSMutableString *str 这些都是指针啊,但是这些指针是指向内容的指针,不是指针的地址,指针地址是&arr和&objc 、&str等
5、arc环境下,编译器会自动的判断,把block自动的从栈copy到堆
6、the block’s flags includes BLOCK_NEEDS_FREE then the block is a heap block (you’ll see why shortly). In this case, all that needs doing is the reference count needs incrementing and then the same block returned.
如果需要释放,我们做的,就是增加引用计数
7、If the block is a global block (recall these from episode 1) then nothing needs doing and the same block is returned. This is because global blocks are effectively singletons.
全局block是全局单例
8、copy三步骤
如果需要free的,证明就是堆的,直接加1就行
如果是global ,global是全局单例,无需处理,直接返回就行。
除了这两种情况,剩下的就是stack 了,需要重新分配内存
9、release 堆上会释放
we made it here and the block is global, then do nothing
但如果是global就不释放了

最后总结

1、NSMutableString , NSMutableArray, NSObject 可以直接传入无需加__block,我们可以在里面可以做如下修改:
修改string的值,array增加元素,减掉元素,object更改属性的值,但是这些都不能赋值nil
2、静态全局变量,静态变量能不加__block,便能修改它们的值。
3、如果要将NSMutableString , NSMutableArray, NSObject置换为nil,或者修改局部变量的值,需要用到__block
4、bound by copy 和 bound by ref
ref 指的事reference ,是指针拷贝, bound by ref 是指针拷贝,bound by copy是值拷贝。
这么说可能是问题,待验证。
5、而且如果此时在Block里面改变a的值是会报错,因为普通变量的值传递为复制,所有Block里的a只是copy过去的a的值,在Block里改变a的值也不会影响外面,编译器避免这个错误就报错。同样的,捕获对象时也是对指针的copy,生成一个指针指向obj对象,所以如果在Block中直接让obj指针指向另外一个对象也会报错。这点编译器已经加了注释// bound by copy。
第五点来源于
作者:WhiteZero
链接:https://www.jianshu.com/p/d96d27819679
6、block里面说不加__block改变不了值,这个值指的是 指针指向的地址不能变,地址里面的内容是可以变的
Bluce li
7、为什么不能在外面赋值,赋的值只是改变了block对象里面的值,没改变外面的值。
8、Block不允许修改外部变量的值,这里所说的外部变量的值,指的是栈中指针的内存地址。 绿 \color{red}{栈区是红灯区,堆区才是绿灯区} 。这句话摘自github一个有名的面试题
9、加了__block后,外面的变量一旦被block俘获进去,这个变量就不再是之前的那个变量了,它的的栈内存地址会变了,其实已经成了一个新的变量了。

自问自答

1、为什么object、mutableStr、mutableArr增加元素、或者改变属性值就行,但是赋值为nil就不行呢
因为赋值nil改变原先指向指针的指针的方向就是(&object)
2、为什么数组print arr 和print &arr不一样呢
arr指向的是内容的地址,存放在堆,&arr指向指针arr的地址,存放在栈,这句话有可能错
3、文中说传入指针或者传入__block就能更改,但实际,object、mutableStr、mutableArr都是指针啊,都不能赋值为nil,说法有问题啊
只能改内容,不能改外面指针指向
4、实例和Class里面都有实例变量,那变量到底放哪里呢
nsobject_impl结构体放了父类以及本类的实例变量,但是Class结构体只放了本类的实例变量
5、有没有什么办法打印Class isa里面究竟有什么实例变量
有用runtime
6、为什么加了__block就能改变指针的值了呢
外面的arr指针和block内部的指针arr是一个哦,因为传入的是一个指针
7、从哪里可以看出,哪里拷贝了,系统自行拷贝吗?
block转为函数指针时,传入了这个结构体,这个结构体,里面有copy 和dispose方法
__main_block_desc_0_DATA
8、经典 review qusetion2 38,very good

调试命令

//打印某个对象的引用计数
_objc_rootRetainCount(obj)
//打印自动缓存池所有的对象
_objc_autoreleasePoolPrint()

特别注意

如果我们想用clang 一个A文件,这个文件里面有很多的其他文件,怎么办呢,直接cd进入这个A文件目录(这个目录当然也包含A文件需要的文件),直接用
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc A.m -o A.cpp

优秀文章(部分观点引自下面文章)

优秀未读文章

附加

转化前1

#import <Foundation/Foundation.h>

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSLog(@"out Hello, World!");
        @autoreleasepool {
             NSLog(@"int Hello, World!");
        }
    }
    return 0;
}

转化后1

int main(int argc, char * argv[]) {
    /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
        NSLog((NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_ec791a_mi_0);
        /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
             NSLog((NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_ec791a_mi_1);
        }
    }
    return 0;
}

转化前2

#import <Foundation/Foundation.h>

int main(int argc, char * argv[]) {
    for (int i = 0; i < 3; i++) {
        @autoreleasepool {
            NSLog(@"out Hello, World!");
        }
    }
    return 0;
}

转化后2

int main(int argc, char * argv[]) {
    for (int i = 0; i < 3; i++) {
        /* @autoreleasepool */ { __AtAutoreleasePool __autoreleasepool; 
            NSLog((NSString *)&__NSConstantStringImpl__var_folders_tj_wxmdttwx7bv3h31ynxs4qc5m0000gn_T_main_b7789e_mi_0);
        }
    }
    return 0;
}
  • 我的猜想
    @autoreleasepool {
    NSLog(@“out Hello, World!”);
    }
    这句代码就会创建一个新的释放池

猜你喜欢

转载自blog.csdn.net/u014544346/article/details/102985591