iOS内存管理 —— TaggedPointer

646 阅读3分钟

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

在这里插入图片描述