iOS底层探索32、内存管理

本文开始对内存管理进行探究分析。

一、内存布局

image.png

内存布局图中,
高地址0xc0000000,针对4G的内存,0xc0000000为3G的位置: 0xc0000000 --> 十进制 --> ÷1024(B) ÷1024(M) ÷1024(G) = 3G
低地址0x00400000,不从0x00000000开始而是留有保留区的原因:
0x00000000 其代表 nil/,保留段一般留给系统处理例如 nil、底层内核发送信号的一些指针地址等。

内存五大区 测试Demo:

相关分析以添加在注释中,不再多做赘述。

@implementation ViewController

int clA;
int clB = 10;

static int bssA;
static NSString *bssStr1;

static int bssB = 10;
static NSString *bssStr2 = @"memorytest";
static NSString *myname = @"Domy";


- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self testStack];
    [self testHeap];
    [self testConst];
}

- (void)testStack {
    NSLog(@"************栈区************");
    // 栈区
    int a = 10;
    int b = 20;
    NSObject *object = [NSObject new];
    NSLog(@"a == \t%p",&a);
    NSLog(@"b == \t%p",&b);
    NSLog(@"object == \t%p",&object);
    NSLog(@"%lu",sizeof(&object));
    NSLog(@"%lu",sizeof(a));
}

- (void)testHeap {
    NSLog(@"************堆区************");
    // 堆区
    NSObject *object1 = [NSObject new];
    NSObject *object2 = [NSObject new];
    NSObject *object3 = [NSObject new];
    NSObject *object4 = [NSObject new];
    NSObject *object5 = [NSObject new];
    NSObject *object6 = [NSObject new];
    NSObject *object7 = [NSObject new];
    NSObject *object8 = [NSObject new];
    NSObject *object9 = [NSObject new];
    NSLog(@"object1 = %@",object1);
    NSLog(@"object2 = %@",object2);
    NSLog(@"object3 = %@",object3);
    NSLog(@"object4 = %@",object4);
    NSLog(@"object5 = %@",object5);
    NSLog(@"object6 = %@",object6);
    NSLog(@"object7 = %@",object7);
    NSLog(@"object8 = %@",object8);
    NSLog(@"object9 = %@",object9);
    // 访问---通过对象->堆区地址->存在栈区的指针
}

- (void)testConst {
    
    // 问题1: 全局变量和局部变量在内存中是否有区别?如果有,是什么区别?
    /**
    全局变量 在全局区,生命周期在整个文件
    局部变量 所在位置位置不定,生命周期局部函数作用域内
    */
    char charA[] = {'a','a','a','a','a','a','a','a','a','a','a'};
    NSLog(@"charA:%p",charA);// 栈 charA:0x7ffeeb9654cd
    char charB;
    NSLog(@"&charB:%p",&charB);// 栈 charB:0x7ffee8eef4b7
    // 静态区 strA:0x108b4f2f8
    NSString *strA = @"张三李四王五";
    NSLog(@"strA:%p",strA);


    // 问题2: Block 是否可以直接修改全局变量? --> 是的,全局变量不进行捕获
//    [UIView animateWithDuration:1 animations:^{
//        myname = @"zhang";
//    }];
//    NSLog(@"myname = %@",myname);// zhang
    
    
    NSLog(@"************静态区************");
    NSLog(@"clA == \t%p",&clA);
    NSLog(@"bssA == \t%p",&bssA);
    NSLog(@"bssStr1 == \t%p",&bssStr1);
    
    NSLog(@"************常量区************");
    NSLog(@"clB == \t%p",&clB);
    NSLog(@"bssB == \t%p",&bssB);
    NSLog(@"bssStr2 == \t%p",&bssStr2);
    

    NSLog(@"************静态区安全测试************");
    // 100 可以修改
    // 只针对文件有效 -
    NSLog(@"vc:%p--%d",&personNum,personNum); // 100
    personNum = 10000;
    NSLog(@"vc:%p--%d",&personNum,personNum); // 10000
    [[MyPerson new] run]; // 100 + 1 = 101
    NSLog(@"vc:%p--%d",&personNum,personNum); // 10000
    [MyPerson eat]; // 102
    NSLog(@"vc:%p--%d",&personNum,personNum); // 10000
   
    [[MyPerson alloc] cate_method];

    
    // 扩展
    MyPerson *p = [MyPerson new];
    p.name = @"name";
    NSLog(@"对象 p:%p -- &p:%p",p,&p);
    /**
     对象p: 0x600001094620  --  对象p 在堆区
     &p:      0x7ffee67374d8    --  指针 在栈区
     */
    // p.name:0x10b0ac400 -- 常量区
    NSLog(@"p.name:%p",p.name);
}

@end

运行工程,输出打印:

五大区Demo[18362:1527836] ************栈区************
五大区Demo[18362:1527836] a ==     0x7ffee58434cc
五大区Demo[18362:1527836] b ==     0x7ffee58434c8
五大区Demo[18362:1527836] object ==    0x7ffee58434c0
五大区Demo[18362:1527836] 8
五大区Demo[18362:1527836] 4
五大区Demo[18362:1527836] ************堆区************
五大区Demo[18362:1527836] object1 = <NSObject: 0x600001004810>
五大区Demo[18362:1527836] object2 = <NSObject: 0x600001004830>
五大区Demo[18362:1527836] object3 = <NSObject: 0x600001004820>
五大区Demo[18362:1527836] object4 = <NSObject: 0x600001004840>
五大区Demo[18362:1527836] object5 = <NSObject: 0x600001004850>
五大区Demo[18362:1527836] object6 = <NSObject: 0x600001004860>
五大区Demo[18362:1527836] object7 = <NSObject: 0x600001004880>
五大区Demo[18362:1527836] object8 = <NSObject: 0x600001004890>
五大区Demo[18362:1527836] object9 = <NSObject: 0x6000010048a0>
五大区Demo[18362:1527836]charA:0x7ffeede744cd
五大区Demo[18456:1536336] &charB:0x7ffeede744b7
五大区Demo[18456:1536336] strA:0x101d8b318
五大区Demo[18362:1527836] ************静态区************
五大区Demo[18362:1527836] clA ==   0x10a3bd524
五大区Demo[18362:1527836] bssA ==  0x10a3bd528
五大区Demo[18362:1527836] bssStr1 ==   0x10a3bd530
五大区Demo[18362:1527836] ************常量区************
五大区Demo[18362:1527836] clB ==   0x10a3bd508
五大区Demo[18362:1527836] bssB ==  0x10a3bd518
五大区Demo[18362:1527836] bssStr2 ==   0x10a3bd510
五大区Demo[18362:1527836] ************静态区安全测试************
五大区Demo[18362:1527836] vc:0x10a3bd51c--100
五大区Demo[18362:1527836] vc:0x10a3bd51c--10000
五大区Demo[18362:1527836] MyPerson内部:-0x10a3bd500--101
五大区Demo[18362:1527836] vc:0x10a3bd51c--10000
五大区Demo[18362:1527836] MyPerson内部:MyPerson-0x10a3bd500--102
五大区Demo[18362:1527836] vc:0x10a3bd51c--10000
五大区Demo[18362:1527836] MyPerson内部:-0x10a3bd520--100
五大区Demo[18362:1527836] 对象 p:0x600001008470 -- &p:0x7ffee58434c8
五大区Demo[18362:1527836] p.name:0x10a3bc400

二、内存管理策略

1、TaggedPointer - 小对象类型

NSString *str = @"";
0xa000000000000621 
 --> 高位 0xa --> 1  010 --> 2   
 --> 低位 621 -->   

int a = ;    
0xb000000000000025 
 --> 高位 0xb --> 1  011 --> 3
 --> 低位 25   --> 
如上,最高位为1,作为标志是否是taggedPointer类型;

2 : string 类型 
3 : int 类型    

TaggedPointer 类型的变量,在iOS14以后,其地址做了一步编码混淆(异或某个值),解码时只要再次异或即可。

TaggedPointer 类型的变量总结:

  1. 指针的值包含:地址 + 值
  2. 值的操作不会进行 retain/release,因此其内存接由系统管理释放回收;
  3. 直接在内存的静态区读取,比普通对象内存读取效率高3倍,创建速度高106倍 (来自WWDC官方公布数据)。

2、引用计数

retain/release 分析

补充,retain操作时,针对 nonpointer类型的ISA,对象是通过散列表进行存取。sideTables 并非所有类都在一个散列表中,但也并非每个类都有自己的一张散列表。通过源码可看到,sideTables 在真机非模拟器上最多可以创建8 张,其他可创建 64 张。

待续......

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,189评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,577评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,857评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,703评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,705评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,620评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,995评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,656评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,898评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,639评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,720评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,395评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,982评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,953评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,195评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,907评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,472评论 2 342

推荐阅读更多精彩内容