设为首页 加入收藏

TOP

block本质探寻七之内存管理(一)
2019-08-26 07:00:51 】 浏览:80
Tags:block 本质 探寻 内存 管理

说明:

<1>阅读本问,请参照block前述文章加以理解;

<2>环境:ARC;

<3>变量类型:基本数据类型或者对象类型的auto局部变量;

一、三种情形

//代码

void test1()
{
    int num = 10;
    __block int age = 20;
    Person *per = [[Person alloc] init];
    void(^block)(void) = ^{
        NSLog(@"%d %d %p", num, age, per);
    };
    block();
}

//打印

2019-01-16 15:42:38.974947+0800 MJ_TEST[2405:192414] 10 20 0x100654220
2019-01-16 15:42:38.975258+0800 MJ_TEST[2405:192414] -[Person dealloc]
Program ended with exit code: 0

//clang:xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-9.0.0 main.m

struct __Block_byref_age_0 {
  void *__isa;
__Block_byref_age_0 *__forwarding;
 int __flags;
 int __size;
 int age;
};


struct __test1_block_impl_0 {
  struct __block_impl impl;
  struct __test1_block_desc_0* Desc;
  int num;
  Person *__strong per;
  __Block_byref_age_0 *age; // by ref
  __test1_block_impl_0(void *fp, struct __test1_block_desc_0 *desc, int _num, Person *__strong _per, __Block_byref_age_0 *_age, int flags=0) : num(_num), per(_per), age(_age->__forwarding) {
    impl.isa = &_NSConcreteStackBlock;
    impl.Flags = flags;
    impl.FuncPtr = fp;
    Desc = desc;
  }
};


static void __test1_block_copy_0(struct __test1_block_impl_0*dst, struct __test1_block_impl_0*src) {_Block_object_assign((void*)&dst->age, (void*)src->age, 8/*BLOCK_FIELD_IS_BYREF*/);_Block_object_assign((void*)&dst->per, (void*)src->per, 3/*BLOCK_FIELD_IS_OBJECT*/);}


static void __test1_block_dispose_0(struct __test1_block_impl_0*src) {_Block_object_dispose((void*)src->age, 8/*BLOCK_FIELD_IS_BYREF*/);_Block_object_dispose((void*)src->per, 3/*BLOCK_FIELD_IS_OBJECT*/);}


static struct __test1_block_desc_0 {
  size_t reserved;
  size_t Block_size;
  void (*copy)(struct __test1_block_impl_0*, struct __test1_block_impl_0*);
  void (*dispose)(struct __test1_block_impl_0*);
}



void test1()
{
    int num = 10;
    __attribute__((__blocks__(byref))) __Block_byref_age_0 age = {(void*)0,(__Block_byref_age_0 *)&age, 0, sizeof(__Block_byref_age_0), 20};
    Person *per = ((Person *(*)(id, SEL))(void *)objc_msgSend)((id)((Person *(*)(id, SEL))(void *)objc_msgSend)((id)objc_getClass("Person"), sel_registerName("alloc")), sel_registerName("init"));
    void(*block)(void) = ((void (*)())&__test1_block_impl_0((void *)__test1_block_func_0, &__test1_block_desc_0_DATA, num, per, (__Block_byref_age_0 *)&age, 570425344));
    ((void (*)(__block_impl *))((__block_impl *)block)->FuncPtr)((__block_impl *)block);
}

分析:根据前述文章可知

<1>ARC模式下,block对象(等号右边大括号)被强指针(等号左边)变量持有(默认为strong)时,系统会自动将block对象从栈区copy到堆区;

<2>当访问实例对象或者__block修饰的基础数据类型变量时,block对象结构体中自动会增加两个函数指针——copy和dispose,分别指向__test1_block_copy_0函数和__test1_block_dispose_0函数;

<3>__block修饰的基础数据类型的变量,系统会自动生成一个新的对象(__Block_byref_age_0),block对象通过该新的对象指针变量(__Block_byref_age_0 *age)来访问基础数据类型变量(int age);

<4>num:直接被block捕捉到其结构体内部,随block一起copy到堆区;其随block对象本身一起销毁(不管是栈区的block还是堆区的block);

<5>per:类对象的访问,当block对象被copy到堆区时,block对象会通过copy函数指针来调用__test1_block_copy_0函数完成对per对象的拷贝;同时此时堆区的block对象会根据该类对象的类型(strong还是weak)来决定对其强引用还是弱引用;

说明:所谓的强引用,是指指针指向某个对象(

首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇笔记:沙盒文件的拷贝 下一篇Swift构造

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目