Objective-C Block内存布局与实现原理详解
1. Block内存布局深度解析在编程领域Block是一种特殊的语法结构它允许我们将代码块作为参数传递或存储在变量中。理解Block的内存布局对于编写高效、安全的代码至关重要。今天我们就来彻底拆解Block在内存中的组织方式。Block本质上是一个对象它包含了执行代码和捕获的变量。在内存中Block由多个部分组成每个部分都有其特定的作用。我们先来看一个简单的Block示例void (^myBlock)(void) ^{ NSLog(This is a block); };这个看似简单的Block在内存中其实有着复杂的结构。接下来我们将从底层角度分析Block的内存布局。2. Block内存布局的核心结构2.1 Block的基本内存布局一个Block在内存中的典型布局包含以下几个关键部分Block描述符(Block Descriptor)捕获的变量(Captured Variables)函数指针(Invoke Function Pointer)标志位(Flags)在64位系统上一个Block的头部通常占用24字节的内存空间。我们可以用以下结构体来表示struct Block_layout { void *isa; volatile int32_t flags; int32_t reserved; void (*invoke)(void *, ...); struct Block_descriptor *descriptor; // 捕获的变量会跟随在这里 };2.2 各组成部分详解2.2.1 isa指针每个Block对象都包含一个isa指针指向它的类。这与其他Objective-C对象的行为一致。根据Block的类型不同isa指针可能指向_NSConcreteGlobalBlock全局Block_NSConcreteStackBlock栈Block_NSConcreteMallocBlock堆Block2.2.2 flags字段flags字段包含了Block的各种属性信息常见的标志位包括enum { BLOCK_HAS_COPY_DISPOSE (1 25), // 有copy和dispose辅助函数 BLOCK_HAS_CTOR (1 26), // 有C构造函数 BLOCK_IS_GLOBAL (1 28), // 是全局Block BLOCK_HAS_STRET (1 29), // 有stret返回值 BLOCK_HAS_SIGNATURE (1 30) // 有签名信息 };2.2.3 invoke函数指针invoke是一个函数指针指向Block的实现代码。当Block被调用时实际上就是通过这个指针来执行对应的函数。2.2.4 descriptor描述符descriptor指针指向Block的描述信息包含以下内容struct Block_descriptor { unsigned long int reserved; unsigned long int size; void (*copy)(void *dst, void *src); void (*dispose)(void *); const char *signature; };3. Block的三种内存类型3.1 全局Block(NSGlobalBlock)全局Block具有以下特点不捕获任何外部变量生命周期与程序相同存储在程序的全局数据区多次使用同一个全局Block实际上是使用同一个对象示例void (^globalBlock)(void) ^{ NSLog(This is a global block); };3.2 栈Block(NSStackBlock)栈Block的特点捕获了外部变量存储在栈上生命周期与所在函数相同函数返回后栈Block就无效了示例int a 10; void (^ __weak stackBlock)(void) ^{ NSLog(This is a stack block: %d, a); };注意在ARC环境下编译器会自动将栈Block复制到堆上所以很难直接观察到栈Block。3.3 堆Block(NSMallocBlock)堆Block的特点由栈Block通过copy操作创建存储在堆上需要手动管理内存(在MRC下)可以跨函数使用示例int b 20; void (^heapBlock)(void) [^{ NSLog(This is a heap block: %d, b); } copy];4. Block的内存管理4.1 Block的copy操作Block的copy操作会根据不同类型有不同的行为全局Blockcopy操作什么也不做直接返回原Block栈Blockcopy操作会将Block从栈复制到堆上堆Blockcopy操作会增加引用计数在MRC环境下我们需要手动管理Block的内存// MRC下 void (^block)(void) [^{ /* ... */ } copy]; // 使用完后需要release [block release];在ARC环境下编译器会自动插入适当的copy/release调用。4.2 Block的循环引用问题由于Block会强引用它捕获的对象因此容易造成循环引用。常见解决方案使用__weak修饰符__weak typeof(self) weakSelf self; self.block ^{ [weakSelf doSomething]; };使用__block修饰符(仅限MRC)__block id blockSelf self; self.block ^{ [blockSelf doSomething]; blockSelf nil; // 打破循环 };5. Block的变量捕获机制5.1 自动变量捕获Block会捕获使用的外部变量但默认情况下是以const方式捕获的即在Block内部不能修改这些变量int value 10; void (^block)(void) ^{ // value 20; // 编译错误 NSLog(%d, value); };5.2 __block变量使用__block修饰的变量可以在Block内部修改__block int mutableValue 10; void (^block)(void) ^{ mutableValue 20; // 可以修改 NSLog(%d, mutableValue); };在底层__block变量会被包装成一个结构体struct __Block_byref_mutableValue_0 { void *__isa; __Block_byref_mutableValue_0 *__forwarding; int __flags; int __size; int mutableValue; };5.3 对象类型的捕获当Block捕获对象时会根据修饰符不同而有不同的行为默认是强引用id obj [[NSObject alloc] init]; void (^block)(void) ^{ NSLog(%, obj); // 强引用obj };使用__weak修饰符__weak id weakObj obj; void (^block)(void) ^{ NSLog(%, weakObj); // 弱引用obj };6. Block的底层实现原理6.1 Block的编译转换编译器会将Block转换为一个结构体和一个函数。例如int a 10; void (^block)(void) ^{ NSLog(%d, a); };会被转换为类似下面的代码struct __block_impl { void *isa; int Flags; int Reserved; void *FuncPtr; }; struct __main_block_impl_0 { struct __block_impl impl; struct __main_block_desc_0 *Desc; int a; }; static void __main_block_func_0(struct __main_block_impl_0 *__cself) { int a __cself-a; NSLog(%d, a); }6.2 Block的调用机制当调用一个Block时实际上是调用了Block结构体中的FuncPtr函数指针并将Block自身作为参数传递// block-invoke(block, ...);这就是为什么在Block内部可以访问到捕获的变量 - 因为它们都存储在Block结构体中。7. 实际应用中的注意事项7.1 性能优化建议避免在循环中创建Block特别是捕获了大量变量的Block对于不捕获变量的Block使用全局Block合理使用__weak避免不必要的强引用7.2 调试技巧使用po [block copy]可以在lldb中查看Block的详细信息通过xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc file.m命令可以查看Block的C实现使用Instruments的Allocations工具可以跟踪Block的内存分配情况7.3 常见问题排查EXC_BAD_ACCESS错误可能是使用了已经释放的栈Block内存泄漏检查是否有循环引用变量值不符合预期确认变量捕获方式是否正确8. 不同语言中的Block实现对比8.1 Objective-C与Swift闭包比较虽然Swift的闭包与Objective-C的Block概念相似但在实现上有一些差异Swift闭包不区分全局/栈/堆闭包Swift的捕获列表语法更明确Swift闭包默认捕获的变量是可变的8.2 C lambda表达式C11引入的lambda表达式与Block类似但有以下区别lambda可以按值或按引用捕获变量lambda可以有模板参数lambda没有自动的内存管理9. 高级话题Block的ABI与跨平台兼容性Block的ABI(应用程序二进制接口)在不同平台上有细微差异iOS/macOS使用统一的Block ABI其他平台可能需要特殊的编译器标志跨语言调用需要注意内存管理和调用约定在编写跨平台代码时需要特别注意Block的内存管理方式和调用约定。10. 实战案例自定义Block内存分配器对于需要高性能的场景我们可以实现自定义的Block内存分配器#import Block.h typedef void (^CustomBlock)(void); CustomBlock CreateCustomBlock(void (^original)(void)) { // 获取原始Block的大小 size_t size Block_size(original); // 分配内存 CustomBlock newBlock Block_copy(original); // 自定义初始化 // ... return newBlock; }这种技术可以用于特殊的内存管理策略或性能优化场景。

相关新闻

【单片机毕业设计推荐】基于 STM32 单片机的老人智能跌倒监测与紧急呼救装置设计,基于 STM32 的多功能环境感知与人体危险预警系统设计(013504)

【单片机毕业设计推荐】基于 STM32 单片机的老人智能跌倒监测与紧急呼救装置设计,基于 STM32 的多功能环境感知与人体危险预警系统设计(013504)

文章目录20 个相关毕业设计备选题目项目研究背景摘要总体方案核心功能技术路线项目演示关于我们项目案例源码获取温馨提示:本人主页置顶文章(点我)有 CSDN 平台官方提供的学长联系方式的名片! 温馨提示:本人主页置顶文章(点我)有 CSDN 平台官…

2026/7/30 4:29:40阅读更多 →
分析SOC芯片:QHD显示器主控芯片scaler IC,DP+HDMI转EDP,LVDS.

分析SOC芯片:QHD显示器主控芯片scaler IC,DP+HDMI转EDP,LVDS.

ICNM8301CG是北京集创北方科技股份有限公司(Chipone)推出的一款多功能显示控制器(Scaler)该芯片是一款高度集成的显示控制器,能够将多个数字视频输入信号(如HDMI、DP)进行缩放(Scale…

2026/7/30 4:29:40阅读更多 →
3步完成QQ空间历史说说完整备份:GetQzonehistory开源工具终极指南

3步完成QQ空间历史说说完整备份:GetQzonehistory开源工具终极指南

3步完成QQ空间历史说说完整备份:GetQzonehistory开源工具终极指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 在数字记忆日益珍贵的今天,GetQzonehistory为您…

2026/7/30 4:29:39阅读更多 →
数字电路设计实战:从亚稳态到跨时钟域处理的工程避坑指南

数字电路设计实战:从亚稳态到跨时钟域处理的工程避坑指南

1. 从“开”与“关”说起:数字世界的基石我们每天使用的手机、电脑、智能手表,其内部最核心的运算与逻辑,都建立在一个看似简单却无比强大的概念之上:用“开”和“关”两种状态来表示一切信息。这就是数字电路的世界。你可能觉得这…

2026/7/30 5:39:54阅读更多 →
计算机单片机毕设实战-基于 YF-S201C 传感器的流量计量预警装置研发 , 基于嵌入式单片机的流量自动切断报警系统实现(010401)

计算机单片机毕设实战-基于 YF-S201C 传感器的流量计量预警装置研发 , 基于嵌入式单片机的流量自动切断报警系统实现(010401)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/30 5:39:54阅读更多 →
终极指南:如何用League Akari本地智能助手提升你的英雄联盟游戏体验

终极指南:如何用League Akari本地智能助手提升你的英雄联盟游戏体验

终极指南:如何用League Akari本地智能助手提升你的英雄联盟游戏体验 【免费下载链接】League-Toolkit An all-in-one toolkit for LeagueClient. Gathering power 🚀. 项目地址: https://gitcode.com/gh_mirrors/le/League-Toolkit 还在为英雄联盟…

2026/7/30 5:39:54阅读更多 →
计算机单片机毕设实战-基于单片机多模式按键控制的空气净化智能设备研发,基于 STM32 的 OLED 空气质量数据显示终端开发(010301)

计算机单片机毕设实战-基于单片机多模式按键控制的空气净化智能设备研发,基于 STM32 的 OLED 空气质量数据显示终端开发(010301)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/30 5:39:54阅读更多 →
单片机毕设项目:. 基于 STM32F103C8T6 的酒精传感数据处理装置,基于单片机的便携式酒精实时显示报警系统设计(010201)

单片机毕设项目:. 基于 STM32F103C8T6 的酒精传感数据处理装置,基于单片机的便携式酒精实时显示报警系统设计(010201)

博主介绍:✌️码农一枚 ,专注于大学生项目实战开发、讲解和毕业🚢文撰写修改等。全栈领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java、小程序技术领域和毕业项目实战 ✌️技术范围:&am…

2026/7/30 5:39:54阅读更多 →
当AI误判偏瘫患者肩关节代偿动作时——康复工程师紧急修复的6小时实战复盘(含实时反馈日志)

当AI误判偏瘫患者肩关节代偿动作时——康复工程师紧急修复的6小时实战复盘(含实时反馈日志)

更多请点击: https://kaifayun.com 第一章:当AI误判偏瘫患者肩关节代偿动作时——康复工程师紧急修复的6小时实战复盘(含实时反馈日志) 凌晨3:17,康复中心AI运动分析系统连续3次将一名右侧偏瘫患者的肩胛上提动作标记…

2026/7/30 5:37:54阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/29 9:47:45阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/29 7:00:19阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/29 7:58:51阅读更多 →
3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 [特殊字符]

3分钟解锁iOS应用自由:TrollInstallerX让你的iPhone摆脱安装限制 🚀 【免费下载链接】TrollInstallerX A TrollStore installer for iOS 14.0 - 16.6.1 项目地址: https://gitcode.com/gh_mirrors/tr/TrollInstallerX 你是否曾经因为iOS系统的严格…

2026/7/30 0:00:58阅读更多 →
[GESP202606 四级] 扫雷

[GESP202606 四级] 扫雷

B4557 [GESP202606 四级] 扫雷 https://www.luogu.com.cn/problem/B4557 中国计算机学会(CCF)2026年6月C四级讲解——扫雷 https://www.bilibili.com/video/BV1MCMg6AEXR/ B4557 [GESP202606 四级] 扫雷 https://www.bilibili.com/video/BV1ZKTj6ZEVh/ 2…

2026/7/30 0:00:58阅读更多 →
Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南

Windows驱动存储终极清理工具:DriverStoreExplorer完全指南 【免费下载链接】DriverStoreExplorer Driver Store Explorer 项目地址: https://gitcode.com/gh_mirrors/dr/DriverStoreExplorer 您是否曾因Windows系统盘空间不足而烦恼?是否遇到过设…

2026/7/30 0:00:58阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/30 0:27:26阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/30 4:47:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/29 14:26:42阅读更多 →