iOS——Block签名
首先来看block结构体对象Block_layout(等同于clang编译出来的__Block_byref_a_0)
#define BLOCK_DESCRIPTOR_1 1
struct Block_descriptor_1 {uintptr_t reserved;uintptr_t size;
};#define BLOCK_DESCRIPTOR_2 1
struct Block_descriptor_2 {// requires BLOCK_HAS_COPY_DISPOSEBlockCopyFunction copy;BlockDisposeFunction dispose;
};#define BLOCK_DESCRIPTOR_3 1
struct Block_descriptor_3 {// requires BLOCK_HAS_SIGNATUREconst char *signature;const char *layout; // contents depend on BLOCK_HAS_EXTENDED_LAYOUT
};struct Block_layout {void *isa;volatile int32_t flags; // contains ref countint32_t reserved;BlockInvokeFunction invoke;struct Block_descriptor_1 *descriptor; //// imported variables
};
其中Block_layout是基础的block结构空间,而部分block则拥有Block_descriptor_2和Block_descriptor_3结构,其中的flags标识记录了一些信息
- 第1位:释放标记,一般常用BLOCK_NEEDS_FREE做位与操作,一同传入flags,告知该block可释放
- 第16位:存储引用计数的值,是一个可选参数
- 第24位:第16位是否有效的标志,程序根据它来决定是否增加火箭少女引用计数位的值
- 第25位:是否拥有拷贝辅助函数
- 第26位:是否拥有block析构函数
- 第27位:标志是否有垃圾回收
- 第28位:标志是否是全局block
- 第30位:与BLOCK_USE_START相对,判断当前block是否拥有一个签名,用于runtime时动态调用
但部分block则拥有Block_descriptor_2和Block_descriptor_3结构这句话又该怎么去理解呢?请看下面的解释
static struct Block_descriptor_2 * _Block_descriptor_2(struct Block_layout *aBlock)
{if (! (aBlock->flags & BLOCK_HAS_COPY_DISPOSE)) return NULL;uint8_t *desc = (uint8_t *)aBlock->descriptor;desc += sizeof(struct Block_descriptor_1);return (struct Block_descriptor_2 *)desc;
}static struct Block_descriptor_3 * _Block_descriptor_3(struct Block_layout *aBlock)
{if (! (aBlock->flags & BLOCK_HAS_SIGNATURE)) return NULL;uint8_t *desc = (uint8_t *)aBlock->descriptor;desc += sizeof(struct Block_descriptor_1);if (aBlock->flags & BLOCK_HAS_COPY_DISPOSE) {desc += sizeof(struct Block_descriptor_2);}return (struct Block_descriptor_3 *)desc;
}
- 如果
aBlock->flags & BLOCK_HAS_COPY_DISPOSE满足,则_Block_descriptor_2存在,反之则block没有_Block_descriptor_2这个结构_Block_descriptor_2可以通过Block_descriptor_1内存偏移得到
- 同理,
aBlock->flags & BLOCK_HAS_SIGNATURE满足,则_Block_descriptor_3存在_Block_descriptor_3可以通过Block_descriptor_2内存偏移得到
决定这两个结构是否存在的绝对因素其实就是Block_layout的flags
// Values for Block_layout->flags to describe block objects
enum {BLOCK_DEALLOCATING = (0x0001), // runtimeBLOCK_REFCOUNT_MASK = (0xfffe), // runtimeBLOCK_NEEDS_FREE = (1 << 24), // runtimeBLOCK_HAS_COPY_DISPOSE = (1 << 25), // compilerBLOCK_HAS_CTOR = (1 << 26), // compiler: helpers have C++ codeBLOCK_IS_GC = (1 << 27), // runtimeBLOCK_IS_GLOBAL = (1 << 28), // compilerBLOCK_USE_STRET = (1 << 29), // compiler: undefined if !BLOCK_HAS_SIGNATUREBLOCK_HAS_SIGNATURE = (1 << 30), // compilerBLOCK_HAS_EXTENDED_LAYOUT=(1 << 31) // compiler
};
接下来就用汇编来看看block中的签名
_ NSGlobalBlock__签名(_ Block_copy进入时)


方法签名在lldb调试中使用po命令,查看block对象的地址
通过方法签名,可以在运行时获取 Block 的参数和返回值类型,帮助程序在调用 Block 时正确地处理数据。
通过方法签名,你可以在运行时动态地调用不同的方法或函数,而不需要提前确定要调用的具体方法。
-
回调机制:方法签名使得你可以将方法或函数作为参数传递给其他方法或函数,从而实现回调机制。
-
反射机制:方法签名在反射机制中发挥重要作用,它允许程序在运行时获取方法的信息,如方法名称、参数个数、参数类型、返回值类型等。
-
适配器模式:在设计模式中,方法签名的使用有助于实现适配器模式,从而使不同接口的方法能够相互调用。
方法签名的含义可查看[[Type Encodings]] -
v: 返回值是void类型。 -
8@?: 参数部分的编码。8代表参数的个数。@代表第一个参数是一个对象类型。?代表第二个参数是一个 Block 类型。0代表没有其他参数。
NSStackBlock

NSMallocBlock

相关文章:
iOS——Block签名
首先来看block结构体对象Block_layout(等同于clang编译出来的__Block_byref_a_0) #define BLOCK_DESCRIPTOR_1 1 struct Block_descriptor_1 {uintptr_t reserved;uintptr_t size; };#define BLOCK_DESCRIPTOR_2 1 struct Block_descriptor_2 {// requi…...
Flutter 图片选取及裁剪
在开发项目里修改用户头像的功能,涉及到图片选取及裁剪,基本实现步骤如下: 1、pubspec.yaml 添加 image_picker: ^1.0.1 image_cropper: ^4.0.1: dependencies:image_picker: ^1.0.1image_cropper: ^4.0.1flutter:sdk: flutter…...
C语言每日一题:11.《数据结构》链表分割。
题目一: 题目链接: 思路一:使用带头链表 1.构建两个新的带头链表,头节点不存储数据。 2.循环遍历原来的链表。 3.小于x的尾插到第一个链表。 4.大于等于x尾插到第二个链表。 5.进行链表合并,注意第二个链表的尾的下一…...
记一次Oracle归档日志异常增长问题的排查过程
Oracle归档日志是Oracle数据库的重要功能,用于将数据库的重做日志文件(Redo Log)保存到归档日志文件(Archive Log)中。归档日志的作用是提供数据库的备份和恢复功能,以及支持数据库的持续性和数据完整性。 …...
Java设计模式——类之间的关系
1.继承关系(泛化) 类与子类的关系,指一个类继承另外的一个类。 2.实现关系 一个类可以实现多个接口,实现所有接口的功能。 3.依赖关系 类B作为类A方法中的局部变量或者参数出现,表示A依赖B。 4.关联关系 类B作为类A中的成员变量出现&#…...
Dockerfile构建Redis镜像
建立工作目录 [rootlocalhost ~]# mkdir redis [rootlocalhost ~]# cd redis/ 编写Dockerfile文件 [rootlocalhost redis]# vim Dockerfile FROM centos:7 MAINTAINER dddd <dddd163.com> RUN yum -y install epel-release && yum -y install redis RUN sed -i …...
C高级DAY2
1.思维导图 2. 递归实现,输入一个数,输出这个数的每一位 递归实现,输入一个数,输出这个数的二进制c 写一个脚本,包含以下内容: 显示/etc/group文件中第五行的内容创建目录/home/ubuntu/copy切换工作路径到…...
Linux 服务管理
在Linux上,服务管理是指对系统中运行的服务进行启动、停止、重启、监控和配置的过程。以下是一些常用的Linux服务管理工具和命令: 1. systemctl:systemctl 是一个Linux系统服务管理工具,可以管理Systemd初始化系统的服务。常见的…...
问题记录 1 页面初始化触发el-form必填校验
bug: 先编辑table某条数据,然后关闭,再去新增的时候就会触发el-form必填校验, 网上搜了一下是因为 rules里触发的方式为change时,赋值数据的格式不一致导致触发校验, 最后也没找到正确的解决方法, 只能用很low方式去解决了 方案1. 把trigger改为 blur 失焦后触发 方案2. 初始化…...
后端整理(JVM、Redis、反射)
1. JVM 文章仅为自身笔记 详情查看一篇文章掌握整个JVM,JVM超详细解析!!! 1.1 什么是JVM jvm是Java虚拟机 1.2 Java文件的编译过程 程序员编写代码形成.java文件经过javac编译成.class文件再通过JVM的类加载器进入运行时数据…...
1. CUDA中的grid和block
1. CUDA中的grid和block基本的理解 Kernel: Kernel不是CPU,而是在GPU上运行的特殊函数。你可以把Kernel想象成GPU上并行执行的任务。当你从主机(CPU)调用Kernel时,它在GPU上启动,并在许多线程上并行运行。 Grid: 当你…...
宝存科技企业级固态硬盘解决方案助力企业应用性能提升
企业级固态硬盘解决方案的核心 企业级固态硬盘市场具有产品附加值高、同时进入门槛高的特征,由于国内外巨头和初创企业竞争依然激烈。想要在竞争中脱颖而出,根本还是要靠产品本身的品质和厂商实力。 企业级固态硬盘适用于各类企业应用场景 企业级固态硬盘…...
《练习100》31~35
题目31 # press any key to change color,do you want to try it. Please hurry up!# 第一种使用颜色配置输出 # 向终端输出彩色字符,色彩的设置由目标终端文字系统和转义字符控制,与具体的编程语言无关 # 参数名称 参数值 # 文字效果 0:终端…...
额外题目第4天|132 673 841 127 684 657
132 我发现困难题往往是在中等题的基础上再多了一步 分割最少次数的回文子串 这道题就是在之前动态规划法找回文子串 (leetcode第5题) 的基础上更多 这题还是用动规来写 思路参考代码随想录 dp数组表示的意义是从0到i最少切割的次数 递推公式是 取0到i中间值 j 如果从 j1到…...
HTTP 状态码的分类和含义
HTTP(Hypertext Transfer Protocol)状态码是由服务器向客户端传输的 HTTP 响应中的一个三位数字代码。它们提供了关于请求的处理状态和结果的信息。以下是一些常见的 HTTP 状态码及其含义: 1xx 信息响应:指示服务器已收到请求&…...
Linux Bridge(网桥)
Linux Bridge简介 Linux Bridge(Linux网桥)是一个软件层面的网络设备,用于在Linux系统中创建和管理网络桥接。它允许将多个物理或虚拟网络接口连接在一起,以创建一个共享相同网络段的网络。 下面是Linux Bridge的一些关键特点和…...
【数据结构】优先队列
优先队列 API初级实现使用堆实现由下至上的堆有序化(上浮)由上至下的堆有序化(下沉)插入和删除元素具体实现 很多情况下我们需要有序的处理输入的元素,但是又不需要输入的元素全部有序,或者不需要一次将它们…...
如何在 Ubuntu 22.04 下编译 StoneDB for MySQL 8.0 | StoneDB 使用教程 #1
作者:双飞(花名:小鱼) 杭州电子科技大学在读硕士 StoneDB 内核研发实习生 ❝ 大家好,我是 StoneDB 的实习生小鱼,目前正在做 StoneDB 8.0 内核升级相关的一些事情。刚开始接触数据库开发没多久,…...
AMEYA360:尼得科科宝旋转型DIP开关系列汇总
旋转型DIP开关 S-4000 电路:BCD(十进制) 代码格式:实码 安装类型:表面贴装 调整位置:顶部 可水洗:无 端子类型:J 引线, 鸥翼型 旋转型DIP开关 SA-7000 电路:BCD(十进制), BCH(十六进制) 代码格式…...
为什么感觉 C/C++ 不火了?
首先C和C是两个非常不一样的编程语言。 C语言在系统开发领域地位非常稳固,几乎没有替代产品。应用层开发近年来略微有被Rust取代的迹象。 C由于支持的编程范式过多,导致不同水平的人写出来的代码质量差异太大,这给软件的稳健性带来了很大的…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
逻辑回归:给不确定性划界的分类大师
想象你是一名医生。面对患者的检查报告(肿瘤大小、血液指标),你需要做出一个**决定性判断**:恶性还是良性?这种“非黑即白”的抉择,正是**逻辑回归(Logistic Regression)** 的战场&a…...
解锁数据库简洁之道:FastAPI与SQLModel实战指南
在构建现代Web应用程序时,与数据库的交互无疑是核心环节。虽然传统的数据库操作方式(如直接编写SQL语句与psycopg2交互)赋予了我们精细的控制权,但在面对日益复杂的业务逻辑和快速迭代的需求时,这种方式的开发效率和可…...
家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...
srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
现代密码学 | 椭圆曲线密码学—附py代码
Elliptic Curve Cryptography 椭圆曲线密码学(ECC)是一种基于有限域上椭圆曲线数学特性的公钥加密技术。其核心原理涉及椭圆曲线的代数性质、离散对数问题以及有限域上的运算。 椭圆曲线密码学是多种数字签名算法的基础,例如椭圆曲线数字签…...
【JavaWeb】Docker项目部署
引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...
pikachu靶场通关笔记22-1 SQL注入05-1-insert注入(报错法)
目录 一、SQL注入 二、insert注入 三、报错型注入 四、updatexml函数 五、源码审计 六、insert渗透实战 1、渗透准备 2、获取数据库名database 3、获取表名table 4、获取列名column 5、获取字段 本系列为通过《pikachu靶场通关笔记》的SQL注入关卡(共10关࿰…...
七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
