本系列博文总结自《Pro Multithreading and Memory Management for iOS and OS X with ARC》
了解了 block的实现,我们接着来聊聊 block 和变量的内存管理。本文将介绍可写变量、block的内存段、__block变量的内存段等内容,看完本文会对 block 和变量的内存管理有更加清晰的认识。
上篇文章举了个例子,在 block 内获取了一个外部的局部变量,可以读取,但无法进行写入的修改操作。在 C 语言中有三种类型的变量,可在 block 内进行读写操作
- 全局变量
- 全局静态变量
- 静态变量
全局变量
和 全局静态变量
由于作用域在全局,所以在 block 内访问和读写这两类变量和普通函数没什么区别,而 静态变量
作用域在 block 之外,是怎么对它进行读写呢?通过 clang 工具,我们发现原来 静态变量
是通过指针传递,将变量传递到 block 内,所以可以修改变量值。而上篇文章中的外部变量是通过值传递,自然没法对获取到的外部变量进行修改。由此,可以给我们一个启示,当我们需要修改外部变量时,是不是也可以像 静态变量
这样通过指针来修改外部变量的值呢?
Apple 早就为我们准备了这么一个东西 —— “__block”
__block 说明符
按照惯例,重写一小段代码看看 __block 的真身
1 2 3 4 5 6 7 8 9 |
/************* 使用 __block 的源码 *************/ int main() { __block int intValue = 0; void (^blk)(void) = ^{ intValue = 1; }; return 0; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
/************* 使用 clang 翻译后如下 *************/ struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; struct __Block_byref_intValue_0 { void *__isa; __Block_byref_intValue_0 *__forwarding; int __flags; int __size; int intValue; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0* Desc; __Block_byref_intValue_0 *intValue; // by ref __main_block_impl_0(void *fp, struct __main_block_desc_0 *desc, __Block_byref_intValue_0 *_intValue, int flags=0) : intValue(_intValue->__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_intValue_0 *intValue = __cself->intValue; // bound by ref (intValue->__forwarding->intValue) = 1; } static void __main_block_copy_0(struct __main_block_impl_0 *dst, struct __main_block_impl_0 *src) { _Block_object_assign((void*)&dst->intValue, (void*)src->intValue, 8/*BLOCK_FIELD_IS_BYREF*/); } static void __main_block_dispose_0(struct __main_block_impl_0 *src) { _Block_object_dispose((void*)src->intValue, 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 = { on-t ">*); } __main_block_desc_0_DATA = { 和变量的内存管理有更加清晰的认识。
上篇文章举了个例子,在 block 内获取了一个外部的局部变量,可以读取,但无法进行写入的修改操作。在 C 语言中有三种类型的变量,可在 block 内进行读写操作
Apple 早就为我们准备了这么一个东西 —— “__block” __block 说明符按照惯例,重写一小段代码看看 __block 的真身
|