iOS:块是否保留栈帧?

iOS: Do blocks retain the stack frame?

为了使块能够工作,可以保留它们必须访问堆栈帧的局部变量。

因为框架必须在函数退出后继续存在,所以我假设该块处理的是原始堆栈框架的副本。

堆栈帧保留一个块还是块保留堆栈帧?

队列是否保留其中的块?

块不保留栈帧。块引用的堆栈变量在堆栈上被引用,直到块被移动到堆中。那时,任何自动变量都随块一起复制,任何 __block 个变量都被复制到堆中。

有关详细信息,请参阅块编程主题中的 Blocks and Variables

栈帧不保留任何东西,也没有任何东西保留栈帧。堆栈帧不能 "do" 任何东西(它们只是堆栈中的偏移量)。而且没有什么可保留的(它们只是堆栈中的偏移量)。堆栈框架无法在其范围退出后继续存在。

队列有效地保留添加到它们的块(并且块有效地保留它们的队列直到它们被执行)。 "effectively" 我的意思是 "there is a strong reference that will prevent it from being destroyed." 这是否通过调用 objc_retain 实际实现是一个实现细节。

编辑:最后一段可能比它阐明的更令人困惑。调用 dispatch_async 实际上是 "copy" 块,而不是保留它。但是这里的术语 "copy" 与它对其他对象的含义并不完全相同。它实际上是指将块从堆栈移动到堆,您的面试官可能正在探索 MRC 问题,即您不保留要保留的块,而是复制它们。但在 ARC 中,这已经隐藏起来,最好从强引用的角度考虑它,这正是我希望表达的观点。当您调用 dispatch_async 时,它会自动为您处理复制块,并在完成时释放块(这是记录在案的行为;请参阅 link;这对于 MRC 和 ARC 都是如此)。所以你不必维护一个单独的块引用来保持它在队列中(那会非常不方便)。

dispatch_queue_create.

中记录了块在执行之前还保持对队列的引用这一事实