IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> iOS内存管理 —— TaggedPointer 和 retain、release 流程分析 -> 正文阅读

[移动开发]iOS内存管理 —— TaggedPointer 和 retain、release 流程分析

1. 内存布局

内存五大区

  • : 存放局部变量,参数,指针,函数,地址一般以0x7开头。栈区的内存通过sp寄存器来定位的。
  • :存放alloc、new开辟内存的对象,地址一般以0x6开头。
  • 全局区(bss):未初始化的全局变量和静态变量,地址一般以0x1开头。
  • 常量区(data):已初始化的全局变量和静态变量,地址一般以0x1开头。
  • 代码区(text):主要用于存放程序运行时的代码,代码会被编译成二进制存进内存的

除了内存五大区,还有内核区和保留区,内核区是系统用来进行内核处理操作的区域,而保留区则是预留给系统处理nil等。oxc0000000只代表了3个G,也就是说4个G的内存里面,分给了内核区一个G。

在这里插入图片描述

2. 内存管理方案

内存管理方案除了MRC和ARC,还有以下三种

  • TaggedPointer: 用来储存小对象的指针例如NSNumber,NSDate等,指针上还存了tag和内容,优化了内存和访问速度。WWDC关于TaggedPointer的介绍.
  • NONPOINTER_ISA: 非指针型isa
  • 散列表: 引用计数表,弱引用表

2.1 模拟器调试TaggedPointer

这里看到NSString 的类型有三个:

  • NSCFConstantString:字符串常量,是一种编译时常量,retainCount值很大,对其操作,不会引起引用计数变化,存储在字符串常量区
  • NSCFString:是在运行时创建的NSString子类,创建后引用计数会加1,存储在堆上
  • NSTaggedPointerString:标签指针,是苹果在64位环境下对NSString、NSNumber等对象做的优化。对于NSString对象来说
    • 当字符串是由数字、英文字母组合且长度小于等于9时,会自动成为NSTaggedPointerString类型,存储在常量区
    • 当有中文或者其他特殊符号时,会直接成为__NSCFString类型,存储在堆区

参考

在这里插入图片描述
接下来去源码搜索TaggedPointer。看到这里有关于playload的位置运算,说明这里有加密和解密的过程。那么接下来就去搜索decode。
在这里插入图片描述
这里看到了_objc_decodeTaggedPointer这个方法,_objc_decodeTaggedPointer还调用了_objc_decodeTaggedPointer_noPermute对pointer进行了异或objc_debug_taggedpointer_obfuscator的操作。
在这里插入图片描述
搜索一下objc_debug_taggedpointer_obfuscator,看到其在initializeTaggedPointerObfuscator进行了初始化。这里如果开启了混淆,那么就会得到一个随机的objc_debug_taggedpointer_obfuscator值,否则就为0。
在这里插入图片描述
在看到这里encode的时候也是异或objc_debug_taggedpointer_obfuscator,这样两次异或就能得到原来的值。
在这里插入图片描述
而之前的左移右移操作,则是在_objc_makeTaggedPointer里面。这里可以看出来先进行移动,在进行加密。
在这里插入图片描述
接下来打印NSTaggedPointerString的地址,向右移三位去掉tag。由于是小端模式,所以从后往前读,读出10799,分别对应kc
在这里插入图片描述
在这里插入图片描述
NSTaggedPointerString的地址第一位的1代表的是这个指针是target pointer,而后面的010也就是2,则代表的是NSString类型。
在这里插入图片描述
那么如果是NSNumber类型的,则是011,也就是3
在这里插入图片描述

2.2 真机调试TaggedPointer

这里看到前面只是标记这个为TaggedPointer,类型的标记跑到最后去了。而前面还有一个0010代表着2,这个是什么呢?是不是代表字符长度呢?
在这里插入图片描述
看到这里asdasdf 分别打印出来的是00110100,代表 34。这里说明确实是代表着字符长度
Y2s,shadow_50,text_Q1NETiBATGluU2h1bklvcw==,size_20,color_FFFFFF,t_70,g_se,x_16)
那么在NSNumber里面这个代表着啥呢?这里看到6的值是2,6.0的值是5。那么是不是代表着类型呢?经过一番实验,得出char0short1int2long3float4double5
在这里插入图片描述

3. NONPOINTER_ISA

之前的文章中介绍过 NONPOINTER_ISA,知道对象的引用计数是存在extra_rc里面的。如果对象的引用计数为 10,那么 extra_rc 为 9。如果引用计数大于 10, 则需要使用到下面的 has_sidetable_rc。

3.1 retain 流程分析

  1. 判断是否为Tagged Pointer,如果是则不进行操作直接返回,否则就往下走
  2. 判断是否为 NONPOINTER_ISA,如果不是则直接通过散列表(sidetable)进行retain操作,这里进行+2是因为散列表将引用计数存在63号位置上,+2相当于63号位上的+1操作。是的话就往下走。
  3. 判断是否正在析构,如果是则进行相关操作后返回
  4. 执行extra_rc+1,即引用计数+1操作,并给一个引用计数的状态标识carry,用于表示extra_rc是否满了(最大值为256)
  5. 如果满了,那么就将一半的引用计数存在散列表,一半存在extra_rc。这里分一半是因为通过extra_rc操作引用计数更加的方便,而散列表则需要先去寻找表,再去找到引用计数存储的地方 进行操作,并且散列表还有开锁解锁的操作。

在这里插入图片描述
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

3.2 release 流程分析

  1. 判断是否为Tagged Pointer,如果是则不进行操作直接返回,否则就往下走
  2. 判断是否为 NONPOINTER_ISA,如果不是则直接通过散列表(sidetable)进行release操作。
  3. 判断是否正在析构,如果是则进行相关操作后返回false
  4. 对extra_rc中的引用计数值进行-1操作,并存储此时的extra_rc状态到carry中
  5. 如果此时的状态carray为0,则走到underflow流程
  6. 判断是否有散列表,如果没有则进行deallocate,发送dealloc消息给对象。如果有则从散列表取一半出来进行–操作后赋值给extra_rc,散列表里面的引用计数也变为原来的一半。
    在这里插入图片描述

4. 面试题

下面代码是否会崩溃呢?这里上面的代码不会崩溃,下面的代码会崩溃。崩溃的原因是一直进行多线程的读和写,写的过程中对新值的retain和对旧值的release。所以会产生一个瞬间旧值已经释放了但是还是继续release,所以崩溃了。那么为什么Tagged Pointer不会有这个问题呢?
在这里插入图片描述
看到rootRetain,发现这里如果是TaggedPointer就不做处理直接return。而rootRelease也是一样的。
在这里插入图片描述
在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-09-08 10:51:10  更:2021-09-08 10:52:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 16:48:02-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码