MST

星途 面试题库

面试题:Objective-C中Block的内存管理基础

请简述Objective-C中Block在栈、堆、全局区的不同存储形式以及对应的内存管理方式,并且说明如何将栈上的Block移动到堆上。
35.1万 热度难度
编程语言Objective-C

知识考点

AI 面试

面试题答案

一键面试

1. Block在栈、堆、全局区的存储形式

  • 栈上:当Block捕获了局部变量时,会在栈上创建。这种Block的生命周期与包含它的函数或方法的栈帧相关联。一旦函数或方法返回,栈上的Block就会被销毁。例如,在函数内部定义的简单Block,如果没有对其进行额外操作,就是在栈上。
  • 堆上:通过copy操作,可以将栈上的Block复制到堆上。堆上的Block生命周期由引用计数管理,类似于其他通过alloc创建的对象。它的生命周期不再依赖于栈帧,只要引用计数不为0,就会一直存在。
  • 全局区:当Block没有捕获任何局部变量(即它是一个空的Block),它会存储在全局区。全局区的Block生命周期和程序一样长,在程序启动时创建,程序结束时销毁。

2. 对应的内存管理方式

  • 栈上:无需手动管理内存,因为栈的销毁由系统自动处理。当函数或方法结束,栈上的Block会随着栈帧的销毁而消失。
  • 堆上:遵循引用计数的内存管理方式。当使用copy将Block复制到堆上时,引用计数加1。当不再需要该Block时,应调用release(在MRC下)或依赖ARC自动减少引用计数,当引用计数为0时,系统会自动释放堆上的Block所占用的内存。
  • 全局区:无需手动管理内存,因为全局区的对象在程序运行期间一直存在,直到程序结束才会被销毁。

3. 将栈上的Block移动到堆上的方法

在Objective-C中,可以通过对Block进行copy操作将其从栈上移动到堆上。例如:

// 定义一个栈上的Block
void (^stackBlock)() = ^{
    NSLog(@"This is a stack block");
};
// 将栈上的Block复制到堆上
void (^heapBlock)() = [stackBlock copy];

在ARC环境下,编译器会自动在合适的地方插入copy操作,比如将Block作为返回值返回或者赋值给强引用属性时,都会自动进行copy操作,将栈上的Block移动到堆上。在MRC环境下,则需要手动调用copy方法来确保Block在堆上,以正确管理其生命周期。