iOS 底层 day24 内存管理 内存布局 Tagged Pointer

一、iOS 程序内存布局

1.重点掌握下图,我们可以理解很多东西
内存布局图
2. 通过下面代码,强化我们的理解
void func(){    //代码区
    printf("func");
}
const int a = 10;   //常量区
int c = 20; //全局数据区
int main() {
    NSString *b = @"我是chinese"; // 字符串在常量区; &b在栈区
    static int d = 30;  //全局数据区
    NSObject *e = [[NSObject alloc] init];//对象在堆区; &e在栈区
    NSLog(@"%p",func);
    NSLog(@"\na=%p\nb=%p\nc=%p\nd=%p\ne=%p\n&e=%p\n", &a, b, &c, &d, e, &e);
}

二、Tagged Pointer

1. Tagged Pointer基本介绍
  • 64bit 开始,iOS 引入了 Tagged Pointer 技术,用于优化 NSNumber、NSDate、NSString 等小对象的存储
  • 在没有使用 Tagged Pointer 之前,NSNumber 等对象需要动态分配内存、维护引用计数器等,NSNumber 指针存储的是堆中 NSNumber 对象的地址值
  • 使用 Tagged Pointer 之后,NSNumber 指针里面存储的数据变成了:Tag+Data,也就是将数据直接存储在了指针中
  • 当指针不够存储数据时,才会使用动态分配内存的方式来存储数据
  • objc_msgSend 能识别 Tagged Pointer,比如 NSNumberintValue 方法,直接从指针提取数据,节省了以前的调用开销
2. 如何判断一个指针是否为 Tagged Pointer
  • iOS 平台,指针最高有效位是 1(第 64bit)
  • Mac 平台,指针最低有效位是 1
3. Tagged Pointer 从代码中窥探它们
- (void)viewDidLoad {
    [super viewDidLoad];
    
    
    NSNumber *a = @1;
    NSNumber *b = @2;
    NSNumber *c = @(2020202020202002022);
    NSLog(@"%p,%p,%p",a,b,c);
    
    NSString *aa = [NSString stringWithFormat:@"123abc"];
    NSString *aa2 = [NSString stringWithFormat:@"123abc"]; // 发现 aa2 的地址值和 aa 是相同的
    NSString *bb = [NSString stringWithFormat:@"abcd"];
    NSString *cc = [NSString stringWithFormat:@"abcabcabcabcabcabcabcabc"];
    NSLog(@"%p,%p,%p,%p",aa,aa2,bb,cc);
    NSLog(@"%@,%@,%@", [aa class], [bb class], [cc class]);
}
  • 输出
Demo[5902:460945] 0xb8736ae365a09e56,0xb8736ae365a09e66,0x600000b6cfa0
Demo[5902:460945] __NSCFNumber,__NSCFNumber,__NSCFNumber
Demo[5902:460945] 0xa8755cc57693bd52,0xa8755cc57693bd52,0xa8736ae52396b850,0x60000059ef40
Demo[5902:460945] NSTaggedPointerString,NSTaggedPointerString,__NSCFString
  • 我们可以从代码中看出:
  • 当字符串够短,能够用指针存下时,OC 就不会创建堆对象,而是使用 Tagged Pointer 技术来表示
  • 两个内容相同的 Tagged Pointer ,他们的指针也是一摸一样的。
  • Tagged Pointer 的地址最高位都是 0b1

你可能感兴趣的:(iOS 底层 day24 内存管理 内存布局 Tagged Pointer)