美文网首页
[8]NSString内存管理

[8]NSString内存管理

作者: 默然走一生 | 来源:发表于2019-05-06 09:31 被阅读0次

NSSting内存

  • 栈区(stack): 这个一般由编译器操作,或者说是系统管理,会存一些局部变量,函数跳转跳转时现场保护(寄存器值保存于恢复),这些系统都会帮我们自动实现,无需我们干预。 所以大量的局部变量,深递归,函数循环调用都可能耗尽栈内存而造成程序崩溃
  • 堆区(heap): 一般由程序员管理,比如alloc申请内存,free释放内存。我们创建的对象也都放在这里
  • 全局区(静态区 static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放。注意:在嵌入式系统中全局区又可分为未初始化全局区:.bss段 和初始化全局区:data段。举例:int a;未初始化的。int a = 10;已初始化的。
  • 常量区:常量字符串就是放在这里的,还有const常量
  • 代码区:存放代码,app程序会拷贝到这里
  • __NSCFConstantString显然是常量字符串,地址0x10c843820自然就是存储在常量区。

  • __NSCFString表示为oc对象,NSString就是封装的CFString,0x6000000315c0地址显示这个字符串对象存储在堆中。

  • NSTaggedPointerString这个类表示这是字符串的一种指针Tagged Pointer,0xa636261646362617这个地址为什么如此与众不同呢,接下来我们就简单介绍这钟字符串的存储指针。

在苹果推出了 采用64位架构的A7双核处理器 iphone 5s的时候,为了节省内存和提高执行效率,苹果提出了Tagged Pointer的概念。先看看原有的对象为什么会浪费内存。假设要存储一个 NSNumber 对象,其值是一个整数。正常情况下,如果这个整数只是一个 NSInteger 的普通变量,那么它所占用的内存是与CPU的位数有关,在32位CPU下占4个字节,在64位CPU下是占8个字节的。而指针类型的大小通常也是与CPU位数相关,一个指针所占用的内存在32位CPU下为4个字节,在64位CPU下也是8个字节。所以一个普通的iOS程序,如果没有Tagged Pointer对象,从32位机器迁移到64位机器中后,虽然逻辑没有任何变化,但这种NSNumber、NSDate一类的对象所占用的内存会翻倍。

对于以前的@""符号创建的字符串还是常量字符串,这个没有改变,但是采用stringWithFormat 等NSString方法的创建字符串对象则有了区别。

在苹果的64位OC实现中,若对象指针的二进制第一位是1,则该指针为Tagged Pointer。
例如0xa000000000000311其中a的2进制为1010,第一位1表示这是Tagged Pointer,010表示这是一个NSTaggedPointerString类;这个地址最后一位表示字符串的数目,这里是0001表示有1位字符串;其中真正用来存储的位数只有中间的14位16进制。这个地址本身其实就存储了字符串的值,可以说是存储在&strS内存中值,只是伪装成了地址,它不需要存储在数据区,也不需要申请堆空间。

NSTaggedPointerString的存储有三种编码方式:ASCII码,六位编码,五位编码。

ASCII码

我们发现NSTaggedPointerString存储内容除去第一位和最后一位,其实只有中间的14位16进制字符,再看ascll码由8位二进制组成,所以这里(14*4) / 8=7,用8位的ascll码的话最多可以存储7个字符。字符串数目0~7之间

[NSString stringWithFormat:@"1"]输出的地址 0xa000000000000311,其中31的2进制是0011 0001,在ascll码表里查找发现正是对应着“1”;

六位编码:

NSTaggedPointerString 采用六位二进制编码,(14*4)/6=9.333…,可以看出最多存储9位字符。字符数目8~9

五位编码:

采用五位二进制编码,(14*4)/5 = 11.2,可以看出这种编码最多存储11位字符。字符数目在10~11

NSTaggedPointerString 存储编码中的六位和五位编码都是根据通常代码中字母使用频率来排序的,但并不是一成不变的,apple会持续更新并统计字母使用频率,系统每次升级都可能不一样,当前第一位是字母e,之后是i,l,o,t…;这两种编码是从左向右的;根据编码位数我们显然也能推测出并不是所有字符都可以进行ascll或者六位五位编码的,当出现这样不能编码的时候,系统也就不会使用NSTaggedPointerString类。

相关文章

  • [8]NSString内存管理

    NSSting内存 栈区(stack): 这个一般由编译器操作,或者说是系统管理,会存一些局部变量,函数跳转跳转时...

  • iOS内存管理详解

    目录 block内存管理 autorelease内存管理 weak对象内存管理 NSString内存管理 new、...

  • NSString内存管理

    NSString的内存优化 OC中的NSString不论是在编译时还是在运行时都做了很多的优化,并不同于普通的对象...

  • NSString 内存管理

    在学习自动释放池与RunLoop的关系的时候发现申明NSString类型的变量未随RunLoop的进入休眠而释放,...

  • Foundation框架---NSString

    //创建字符串的方式 NSString*str3 =@"iOS";//系统会对内存自动做管理 NSString *...

  • iOS NSString 内存管理

    iOS中,NSString对象相对其他OC对象的内存管理是复杂的。按照产生对象的isa,大致可以分为三种情况,如下...

  • NSString 的内存管理

    前段时间看了同事的分享,于是把它记录下来 先看下这几个测试代码,关于 NSString: 执行后打印输出结果: 可...

  • iOS strong和copy的区别

    在iOS开发中,几乎每天都会遇到NSString属性的声明, 在ARC内存管理机制下, NSString属性声明有...

  • Ios面试复习--NSString的内存管理

    1.NSString类的内存管理 2.NSString 类型的属性 的@property修饰符号 参考文章第6部分...

  • iOS基础:内存管理-NSString相关知识

    前言 本文主要讲的是NSString类有关的内存管理基础知识。 正文 一、面试常问的问题:为什么NSString的...

网友评论

      本文标题:[8]NSString内存管理

      本文链接:https://www.haomeiwen.com/subject/reiloqtx.html