美文网首页
iOS循序渐进篇三:iOS内存组成情况介绍

iOS循序渐进篇三:iOS内存组成情况介绍

作者: song91425 | 来源:发表于2020-12-27 10:09 被阅读0次

    1、前言

          iOS的内存可分为五大块:栈区、堆区、常量区、全局区(静态区)、代码区。

    1.1 堆区, 栈区, 常量区的内存首地址:

    栈区 : 0x7xxxx
    堆区 : 0x6xxxx
    常量区和静态变量区 : 0x1xxxx

    1.2 iOS内存分区可视化

    image.png

    如下面的代码

       int a = 0;//0存放在初始化的全局区(数据区)
       NSString *str;//未初始化区(BSS区)str地址是在栈,但是str的指向地址是全局区
       static NSString *staticString = @"kep";//静态初始化全局区 staticString的地址是在全局区,它的指向也是全局区
       @implementation ViewController
    
       - (void)viewDidLoad {
           [super viewDidLoad];
           int b=1;//在栈上
           static int c =123; // 分配在静态区
           const NSString * cStr = @"lss"; // cStr分配在栈上,它的指向是常量区
           static NSString *sStr = @"lss2";  // sStr 分配在静态区,它的指向也是常量区
           NSString * str = @"lss3"; //str分配在栈上,指向的是常量区
           NSMutableArray * arr= [NSMutableArray array ]; //arr在栈中,指向堆区的地址
    
           //  定义一个加法计算方法
           int add = [self addWithNumber:2 andOtherNumber:3]; // add存在栈区
           NSLog(@"b内存地址:%p",&b); // b内存地址:0x7ffeeba5013c
           NSLog(@"c内存地址:%p",&c); // c内存地址:0x1041fde80
           NSLog(@"cStr内存地址:%p",&cStr);// cStr内存地址:0x7ffeeba50130
           NSLog(@"cStr指向的内存地址:%p",cStr);// cStr指向的内存地址:0x1041eb310
    
           NSLog(@"sStr内存地址:%p",&sStr);// sStr内存地址:0x1041fde88
           NSLog(@"sStr指向的内存地址:%p",sStr);// sStr指向的内存地址:0x1041eb330
    
           NSLog(@"arr内存地址:%p",&arr);// arr内存地址:0x7ffeeba50120
           NSLog(@"arr指向的内存地址:%p",arr);// arr指向的内存地址:0x600003bd1e00
    
           NSLog(@"add内存地址:%p",&add);//add内存地址:0x7ffeeba5011c
    
           // 全局区
           NSLog(@"a内存地址:%p",&a);// a内存地址:0x1041fe628
           NSLog(@"str内存地址:%p",&str);// str内存地址:0x7ffeeba50128
           NSLog(@"str指向的内存地址:%p",str);// str指向的内存地址:0x1041eb350
    
           NSLog(@"staticString内存地址:%p",&staticString);// staticString内存地址:0x1041fde78
           NSLog(@"staticString指向的内存地址:%p",staticString);// staticString指向的内存地址:0x1041eb2f0
       }
       - (int) addWithNumber:(int)num1 andOtherNumber:(int)num2{
           NSLog(@"num1内存地址:%p",&num1);// num1内存地址:0x7ffeeba500cc
           return num1 + num2;//存在栈区
       }
    
    1.1 栈区

          它是由编译器自动分配和管理的,函数的执行对应着栈的出栈和进栈,所以随着函数执行结束,栈所占内存也将会被释放掉。所以对栈的内存管理,由系统直接完成。栈区分配的内存是连续的,并且由编译器自动分配释放。具体一点就是创建的局部变量,存放函数的参数值等,也就是对应{}里面的对象。在{}括号里除了通过alloc/new/copy/mutableCopy申请的对象(对象存在堆区)或者通过static/const申请的对象(对象存放在全局区/常量区),其他对象都是存放在栈上,包括{}里调用的函数的返回值。注意由const声明的指针是存放在栈上的,指针的指向才是常量区。

    1.2 堆区

          这个区域是iOS的ARC作用的区域,我们在代码中通过alloc/new/copy/mutableCopy的声明对象它是存放在堆区,但是指向它的指针存放在栈区,堆区分配的内存是非连续的,一般由程序员分配释放,若程序员不释放,待程序结束时,由系统回收。
    NSObject *o = [NSObject new]; // o指针分配在栈区,[NSObject new]创建的对象分配在堆区,o指针指向堆区的对象
          在iOS中ARC管理的是OC对象,那么问题来了,什么是OC对象?从底层上讲OC对象是指在堆区存储的数据结构。从iOS层次上来看,凡是首地址是*isa的指针,就可以看成OC对象,比如id、NSObject在堆区开辟的空间。比如:
                                              NSObject *obj = [NSObject alloc];
           我们通常认为obj是一个对象,但是严格来说obj是一个指针, [NSObject alloc] 才是一个对象 ,[NSObject alloc] 执行完后,会在堆上开辟一个内存,这块内存里的东西才叫做对象,而obj只是一个指针,这个指针存储的是这块内存的首地址,它类似字典的索引页,通过索引页所指的页找到想要的对象。所以说obj是一个也是可以的,它就代表着在堆里的那块内存

    1.3 常量区

           这块区域是iOS基础类型和字符串常量存放区域。比如通过int、float、double声明的常量和const声明的常量。这个区待程序执行结束时,由系统释放。

    int a = 0; // 0数值在常量区存储,a存在栈区
    float b =2;// 2数值在常量区存储,b存在栈区
    const NSString *str = @"lss"; // 常量区
    

    1.4 全局区/静态区

           全局区/静态区存放的是静态变量,静态全局变量,以及全局变量。这块内存可以细分为数据区和BBS区,它们的区别在于声明的对象是否初始化,如果初始化那就分配在数据区,未初始化就分配在BBS区。这个区待程序执行结束时,由系统释放。

    int a=0; // 初始化的全局变量(数据区)
    NSString *str;// 未初始化的全局变量(BBS区)
    static NSString *string = @"123"; // 初始化全局静态变量(数据区)
    int main(){
    // 省略多行代码
    };
    

    1.5 代码区

           代码段是用来存放可执行文件的操作指令(存放函数的二进制代码),也就是说是它是可执行程序在内存种的镜像。代码段需要防止在运行时被非法修改,所以只准读取操作,而不允许写入(修改)操作——它是不可写的。这个区待程序执行结束时,由系统释放。参考

    相关文章

      网友评论

          本文标题:iOS循序渐进篇三:iOS内存组成情况介绍

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