当前位置: 首页 > news >正文

__block的深入研究

  • __block可以用于解决block内部无法修改auto变量值的问题

  • __block不能修饰全局变量、静态变量(static)

    • 编译器会将__block变量包装成一个对象

调用的是,从__Block_byref_a_0的指针找到 a所在的内存,然后修改值
Pasted image 20230726145216.png

第一层拷贝(block)

block中的第一层拷贝其实已经讲过了——_Block_copy将block从栈拷贝到堆

第二层拷贝(捕获变量的内存空间)

Pasted image 20230725201046.png

在函数声明时会传__main_block_desc_0_DATA结构体,在里面又会去调用__main_block_copy_0函数,__main_block_copy_0里面会调用_Block_object_assign——这就是第二层拷贝的调用入口。
根据flags & BLOCK_ALL_COPY_DISPOSE_FLAGS进到不同分支来处理捕获到的变量
Pasted image 20230726154645.png

此时捕获到的变量是被__block修饰的BLOCK_FIELD_IS_BYREF类型,就会调用*dest = _Block_byref_copy(object);

static struct Block_byref *_Block_byref_copy(const void *arg) {// 临时变量的保存struct Block_byref *src = (struct Block_byref *)arg;if ((src->forwarding->flags & BLOCK_REFCOUNT_MASK) == 0) {// src points to stack// 用原目标的大小在堆区生成一个Block_byrefstruct Block_byref *copy = (struct Block_byref *)malloc(src->size);copy->isa = NULL;// byref value 4 is logical refcount of 2: one for caller, one for stackcopy->flags = src->flags | BLOCK_BYREF_NEEDS_FREE | 4;// 原来的区域和新的区域都指向同一个对象,使得block具备了修改能力copy->forwarding = copy; // patch heap copy to point to itselfsrc->forwarding = copy;  // patch stack to point to heap copycopy->size = src->size;if (src->flags & BLOCK_BYREF_HAS_COPY_DISPOSE) {// Trust copy helper to copy everything of interest// If more than one field shows up in a byref block this is wrong XXXstruct Block_byref_2 *src2 = (struct Block_byref_2 *)(src+1);struct Block_byref_2 *copy2 = (struct Block_byref_2 *)(copy+1);copy2->byref_keep = src2->byref_keep;copy2->byref_destroy = src2->byref_destroy;if (src->flags & BLOCK_BYREF_LAYOUT_EXTENDED) {struct Block_byref_3 *src3 = (struct Block_byref_3 *)(src2+1);struct Block_byref_3 *copy3 = (struct Block_byref_3*)(copy2+1);copy3->layout = src3->layout;}// 第三层拷贝(*src2->byref_keep)(copy, src);}else {// Bitwise copy.// This copy includes Block_byref_3, if any.memmove(copy+1, src+1, src->size - sizeof(*src));}}// already copied to heapelse if ((src->forwarding->flags & BLOCK_BYREF_NEEDS_FREE) == BLOCK_BYREF_NEEDS_FREE) {latching_incr_int(&src->forwarding->flags);}return src->forwarding;
}

用原目标name的大小在堆区生成一个Block_byref
copy->forwarding = copy; & src->forwarding = copy;——原来的区域和新的区域都指向同一个对象,使得block具备了修改能力
(* src2->byref_keep)(copy, src)开始第三层拷贝

第三层拷贝(拷贝对象)

(*src2->byref_keep)(copy, src)点进去会来到Block_byref结构来,而byref_keepBlock_byref的第5个属性

struct Block_byref {void * __ptrauth_objc_isa_pointer isa;struct Block_byref *forwarding;volatile int32_t flags; // contains ref countuint32_t size;
};struct Block_byref_2 {// requires BLOCK_BYREF_HAS_COPY_DISPOSEBlockByrefKeepFunction byref_keep;BlockByrefDestroyFunction byref_destroy;
};struct Block_byref_3 {// requires BLOCK_BYREF_LAYOUT_EXTENDEDconst char *layout;
};

Pasted image 20230726154841.png

第5位就等于byref_keep,所以在第二层拷贝时会调用__Block_byref_id_object_copy_131

static void __Block_byref_id_object_copy_131(void *dst, void *src) {_Block_object_assign((char*)dst + 40, *(void * *) ((char*)src + 40), 131);
}
static void __Block_byref_id_object_dispose_131(void *src) {_Block_object_dispose(*(void * *) ((char*)src + 40), 131);
}

这个(char*)dst + 40看到__Block_byref_name_0就顿悟了,刚好取得变量name对象。

struct __Block_byref_name_0 {void *__isa;
__Block_byref_name_0 *__forwarding;int __flags;int __size;void (*__Block_byref_id_object_copy)(void*, void*);void (*__Block_byref_id_object_dispose)(void*);NSString *name;
};

_Block_object_assign在对BLOCK_FIELD_IS_OBJECT情况时会做出如下操作:

	case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT:case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK:/*******// copy the actual field held in the __block container// Note this is MRC unretained __block only. // ARC retained __block is handled by the copy helper directly.__block id object;__block void (^object)(void);[^{ object; } copy];********/*dest = object;break;

block捕获的外接变量由ARC自动管理,捕获到name进行拷贝
block中有三层拷贝:拷贝block、拷贝捕获变量的内存地址、拷贝对象

_ Block_object_dispose

void _Block_object_dispose(const void *object, const int flags) {switch (os_assumes(flags & BLOCK_ALL_COPY_DISPOSE_FLAGS)) {case BLOCK_FIELD_IS_BYREF | BLOCK_FIELD_IS_WEAK:case BLOCK_FIELD_IS_BYREF:// get rid of the __block data structure held in a Block_Block_byref_release(object);break;case BLOCK_FIELD_IS_BLOCK:_Block_release(object);break;case BLOCK_FIELD_IS_OBJECT:_Block_release_object(object);break;case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT:case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK:case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_OBJECT | BLOCK_FIELD_IS_WEAK:case BLOCK_BYREF_CALLER | BLOCK_FIELD_IS_BLOCK  | BLOCK_FIELD_IS_WEAK:break;default:break;}
}
// API entry point to release a copied Block
void _Block_release(const void *arg) {struct Block_layout *aBlock = (struct Block_layout *)arg;if (!aBlock) return;if (aBlock->flags & BLOCK_IS_GLOBAL) return;if (! (aBlock->flags & BLOCK_NEEDS_FREE)) return;if (latching_decr_int_should_deallocate(&aBlock->flags)) {_Block_call_dispose_helper(aBlock);_Block_destructInstance(aBlock);free(aBlock);}
}
  • 如果是释放对象就什么也不做(自动释放)
  • 如果是__block修饰,就将指向指回原来的区域并使用free释放

相关文章:

__block的深入研究

__block可以用于解决block内部无法修改auto变量值的问题 __block不能修饰全局变量、静态变量(static) 编译器会将__block变量包装成一个对象 调用的是,从__Block_byref_a_0的指针找到 a所在的内存,然后修改值 第一层拷贝&…...

Segment anything(图片分割大模型)

目录 1.Segment anything 2.补充图像分割和目标检测的区别 1.Segment anything 定义:图像分割通用大模型 延深:可以预计视觉检测大模型,也快了。 进一步理解:传统图像分割对于下图处理时,识别房子的是识别房子的模型…...

【雕爷学编程】MicroPython动手做(27)——物联网之掌控板小程序3

知识点:什么是掌控板? 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片,支持WiFi和蓝牙双模通信,可作为物联网节点,实现物联网应用。同时掌控板上集成了OLED…...

Java中集合容器详解:简单使用与案例分析

目录 一、概览 1.1 Collection 1. Set 2. List 3. Queue 1.2 Map 二、容器中的设计模式 迭代器模式 适配器模式 三、源码分析 ArrayList 1. 概览 2. 扩容 3. 删除元素 4. 序列化 5. Fail-Fast Vector 1. 同步 2. 扩容 3. 与 ArrayList 的比较 4. 替代方案…...

机器学习04-数据理解之数据可视化-(基于Pima数据集)

什么是数据可视化? 数据可视化是指通过图表、图形、地图等视觉元素将数据呈现出来的过程。它是将抽象的、复杂的数据转化为直观、易于理解的视觉表达的一种方法。数据可视化的目的是帮助人们更好地理解数据,从中发现模式、趋势、关联和异常,从而作出更明…...

百度@全球开发者,见证中国科技超级“碗”!

潮汐涌动时,变化悄然发生。2023年全球AI浪潮迭起,大语言模型热度空前,生成式人工智能为千行百业高质量发展带来更多想象空间,一个蓬勃创新、重构万物的“大模型时代”正蓄势待发。 滴滴滴~百度全球开发者,…...

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(一)

说明:请先自行安装好docker再来看本篇文章,本篇文章主要实现通过使用docker部署mysql实现读写分离,并连接数据库测试。第二篇将实现使用Shardingjdbc实现springboot的读写分离实现。 基于Docker去创建Mysql的主从架构 #创建主从数据库文件夹…...

Ajax跨域问题

什么是跨域问题? 跨域问题来源于JavaScript的"同源策略",即只有 协议主机名端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的&…...

Vue + FormData + axios实现图片上传功能

当使用Vue FormData axios实现图片上传功能时,你可以按照以下步骤进行操作: 示例代码 首先,在Vue组件中,创建一个data属性来存储选择的文件和上传状态: data() {return {file: null,uploading: false}; }在模板中…...

设计模式系列:经典的单例模式

单例模式,是设计模式当中非常重要的一种,在面试中也常常被考察到。 正文如下: 一、什么时候使用单例模式? 单例模式可谓是23种设计模式中最简单、最常见的设计模式了,它可以保证一个类只有一个实例。我们平时网购时用的购物车,就是单例模式的一个例子。想一想,如果购物…...

macbook pro 散热解决办法

结论: 2017 macbook pro 13.3 寸 控制住温度, 不惧长时间满载、性能也飞起. 方案说明最低温度满载温度一、终极方案(成本 460元)120w半导体散热 导热垫31度71度二、推荐方案, 完全静音(成本 50元)828散热风扇 导热垫43度81度三、不拆机、低成本(20元)828散热风扇56度91度四、…...

高并发与性能优化的神奇之旅

作为公司的架构师或者程序员,你是否曾经为公司的系统在面对高并发和性能瓶颈时感到手足无措或者焦头烂额呢?笔者在出道那会为此是吃尽了苦头的,不过也得感谢这段苦,让笔者从头到尾去探索,找寻解决之法。 目录 第一站&…...

Django Rest_Framework(一)

1. Web应用模式 在开发Web应用中,有两种应用模式: 前后端不分离[客户端看到的内容和所有界面效果都是由服务端提供出来的。] 前后端分离【把前端的界面效果(html,css,js分离到另一个服务端或另一个目录下,python服务…...

VB+ACCESS智能公交考勤系统管理软件设计与实现

智能公交考勤系统管理软件设计 摘要:随着现代科学技术的发展,越来越多的企业对职工的考勤管理都实行了信息化管理,使用计算机系统代替繁琐冗余的手工方式来管理考勤事务。针对公交考勤的系统管理、人事管理、运营管理,提出了智能公交考勤管理系统。 智能公交考勤系统是典…...

企业电子招标采购系统源码Spring Boot + Mybatis + Redis + Layui + 前后端分离 构建企业电子招采平台之立项流程图 tbms

 项目说明 随着公司的快速发展,企业人员和经营规模不断壮大,公司对内部招采管理的提升提出了更高的要求。在企业里建立一个公平、公开、公正的采购环境,最大限度控制采购成本至关重要。符合国家电子招投标法律法规及相关规范&am…...

【ES】笔记-ECMAScript 相关介绍

ECMASript 相关介绍 什么是ECMA ECMA(European Computer Manufacturers Association)中文名称为欧洲计算机制 造商协会,这个组织的目标是评估、开发和认可电信和计算机标准。1994 年后该 组织改名为 Ecma 国际。 什么是 ECMAScript ECMAS…...

FFmpeg下载安装及Windows开发环境设置

1 FFmpeg简介 FFmpeg:FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。项目的名称来自MPEG视频编码标准,前面的"FF"代表…...

transformer面试常考题

1.位置编码有哪些?有什么区别? nn.embedding和正余弦编码两种用的多。nn.embedding是一种基于学习的嵌入方法, 通过神经网络的训练过程, 会自动学习数据中每个符号的嵌入向量表示。 而正余弦编码是一种手工设计的嵌入方式&…...

aws的EC2云服务器

亚马逊官网有免费试用1年的服务器 1. 启动生成实例 1.1 创建实例时需要生成 使用的默认的 Amazon Linux 和 一个.pem后缀的秘钥 1.2 网上下一个Mobaxterm ,实例名是公有 IPv4 DNS 地址 ,使用SSH连接,登录名是ec2-user...

hive函数大全

在hive内部有许多函数&#xff0c;如下&#xff1a; 内置运算符 关系运算符 算术运算符 逻辑运算符 复杂类型函数 内置函数内置聚合函数 数学函数 收集函数 类型转换函数 日期函数 条件函数 字符函数 内置聚合函数 内置表生成函数 1.1关系运算符 等值比较: 等值比较:<>…...

MiniCPM-V-2_6代码截图理解:函数逻辑分析+注释生成效果展示

MiniCPM-V-2_6代码截图理解&#xff1a;函数逻辑分析注释生成效果展示 1. 引言&#xff1a;当AI能看懂代码截图 你有没有遇到过这样的情况&#xff1a;看到一个复杂的代码截图&#xff0c;想要理解其中的函数逻辑&#xff0c;却需要一行行手动输入代码&#xff1f;或者面对一…...

Emotion2Vec+语音情感识别系统:5分钟快速部署,9种情绪一键分析

Emotion2Vec语音情感识别系统&#xff1a;5分钟快速部署&#xff0c;9种情绪一键分析 1. 系统介绍与核心价值 1.1 什么是Emotion2Vec Emotion2Vec是一款基于深度学习的语音情感识别系统&#xff0c;能够自动分析语音中蕴含的情绪状态。这个由科哥二次开发构建的镜像版本&…...

不用Animator!用Playable+Timeline打造Unity自定义动画状态机(含项目代码片段)

突破Animator限制&#xff1a;Playable与Timeline构建Unity高阶动画系统 在Unity游戏开发中&#xff0c;动画系统一直是角色表现的核心。传统Animator虽然入门简单&#xff0c;但当项目复杂度上升时&#xff0c;状态机臃肿、过渡僵硬、调试困难等问题逐渐暴露。许多中高级开发…...

Phi-4-mini-reasoning在ollama中启用flash attention:推理速度提升实测报告

Phi-4-mini-reasoning在ollama中启用flash attention&#xff1a;推理速度提升实测报告 你是否遇到过这样的场景&#xff1a;部署了一个轻量级推理模型&#xff0c;满怀期待地输入问题&#xff0c;结果等待了十几秒才得到回复&#xff1f;对于需要快速响应的应用&#xff0c;比…...

BilibiliDown完整指南:三步掌握B站视频批量下载技巧

BilibiliDown完整指南&#xff1a;三步掌握B站视频批量下载技巧 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader &#x1f633; 项目地址: https://gitcode.com/gh_mirrors/bi/…...

Wan2.1-umt5模型部署排错指南:解决403 Forbidden等常见API错误

Wan2.1-umt5模型部署排错指南&#xff1a;解决403 Forbidden等常见API错误 最近在折腾Wan2.1-umt5模型&#xff0c;想把它部署起来对外提供API服务&#xff0c;结果踩了不少坑。最让人头疼的就是各种HTTP错误码&#xff0c;比如403 Forbidden、502 Bad Gateway&#xff0c;有时…...

Python自动化运维实战:用Paramiko库5分钟搞定SSH批量管理(附完整代码)

Python自动化运维实战&#xff1a;用Paramiko库5分钟搞定SSH批量管理&#xff08;附完整代码&#xff09; 运维工程师的日常工作中&#xff0c;服务器管理往往占据大量时间。想象一下&#xff0c;当你需要同时更新50台服务器的安全补丁&#xff0c;或者批量收集100台设备的日志…...

CDAN不只是论文里的公式:深入浅出图解‘条件对抗’如何让领域自适应更精准

CDAN不只是论文里的公式&#xff1a;深入浅出图解‘条件对抗’如何让领域自适应更精准 想象你是一位冰淇淋品鉴师&#xff0c;需要将一家老牌店铺&#xff08;源域&#xff09;的配方迁移到新店铺&#xff08;目标域&#xff09;。传统方法粗暴混合所有原料&#xff0c;导致巧…...

零代码自动化:OpenClaw+百川2-13B实现Excel报表智能整理

零代码自动化&#xff1a;OpenClaw百川2-13B实现Excel报表智能整理 1. 为什么需要智能表格处理工具 每个月末&#xff0c;我都要面对几十张格式各异的Excel报表。供应商对账单、部门报销明细、项目进度表……这些文件总是以不同的结构出现在我的邮箱里。最痛苦的不是处理数据…...

mPLUG视觉问答效果展示:交通标志识别、菜单文字理解、图表数据问答

mPLUG视觉问答效果展示&#xff1a;交通标志识别、菜单文字理解、图表数据问答 获取更多AI镜像 想探索更多AI镜像和应用场景&#xff1f;访问 CSDN星图镜像广场&#xff0c;提供丰富的预置镜像&#xff0c;覆盖大模型推理、图像生成、视频生成、模型微调等多个领域&#xff0c;…...