返回

探究block的底层原理(下)

IOS

block的底层原理

内存管理

block在内存中是如何存储和管理的呢?

首先,block本身是一个对象,因此它也会被分配在堆内存中。但是,block中的变量却可以存储在栈内存中。这是因为block在创建时,会创建一个栈帧,栈帧中存储着block的局部变量。

当block被调用时,它会创建一个新的栈帧,新的栈帧中存储着block的参数和局部变量。当block执行完毕后,新的栈帧会被销毁,但block本身仍然存在于堆内存中。

栈帧

栈帧是用来存储函数参数、局部变量和临时值的内存区域。栈帧在函数调用时创建,在函数返回时销毁。栈帧的大小由函数所使用的变量的数量和大小决定。

block在创建时也会创建一个栈帧,栈帧中存储着block的局部变量。当block被调用时,它会创建一个新的栈帧,新的栈帧中存储着block的参数和局部变量。当block执行完毕后,新的栈帧会被销毁,但block本身仍然存在于堆内存中。

堆是用来存储动态分配对象的内存区域。堆中的对象可以通过指针来访问。当一个对象不再使用时,可以通过释放指针来释放对象所占用的内存。

block本身就是一个动态分配的对象,因此它被存储在堆内存中。当block被创建时,系统会为它分配一块内存空间。当block不再使用时,可以通过释放指针来释放block所占用的内存。

ARC

ARC(Automatic Reference Counting)是一种自动引用计数的内存管理机制。ARC可以自动跟踪对象的引用计数,并在引用计数为0时释放对象所占用的内存。

在ARC下,block的引用计数是通过block指针来管理的。当一个block被赋值给一个变量时,该变量的引用计数会增加1。当一个block被释放时,该变量的引用计数会减少1。当一个block的引用计数为0时,该block会被释放。

循环引用

循环引用是指两个或多个对象相互引用,导致无法被释放的情况。循环引用会导致内存泄漏,因为系统无法自动释放循环引用的对象。

block也可以导致循环引用。例如,如果一个block捕获了一个强引用变量,那么该强引用变量就会持有对block的引用。同时,block又持有对强引用变量的引用。这样就形成了一个循环引用。

为了避免block导致循环引用,可以使用weak引用变量来捕获对象。weak引用变量不会增加对象的引用计数,因此不会导致循环引用。

内存泄漏

内存泄漏是指程序中存在无法被释放的对象,导致内存被占用而无法被重新使用的情况。内存泄漏会导致程序的性能下降,甚至崩溃。

block也可能导致内存泄漏。例如,如果一个block捕获了一个强引用变量,那么该强引用变量就会持有对block的引用。同时,block又持有对强引用变量的引用。这样就形成了一个循环引用。循环引用会导致内存泄漏,因为系统无法自动释放循环引用的对象。

为了避免block导致内存泄漏,可以使用weak引用变量来捕获对象。weak引用变量不会增加对象的引用计数,因此不会导致循环引用。