平时我们编写程序的时候可能不太在意系统的内存问题,那么我们所编写代码变量都是怎么在内存中存取的呢?内存其实分为五大分区,栈区(系统管理的地方)堆区(程序员控制的地方)常量区(全局区)静态区代码区,下面我们来简单介绍介绍。

首先我们要知道,这里说的内存指的就是RAM

一、五大分区

1.栈区

创建临时变量时由编译器自动分配,在不需要的时候自动清除的变量的存储区。

里面的变量通常是局部变量、函数参数等。在一个进程中,位于用户虚拟地址空间顶部的是用户栈,编译器用它来实现函数的调用。和堆一样,用户栈在程序执行期间可以动态地扩展和收缩。

优点:

  • 栈是系统数据结构,对应线程/进程是唯一的。
  • 快速高效,缺点是有限制,数据不灵活。[先进后出]
  • 栈空间分静态分配和动态分配两种。
  • 静态分配是编译器完成的,比如自动变量(auto)的分配。
  • 动态分配由alloc函数完成。
  • 栈的动态分配无需释放(是自动的),也就没有释放函数。
  • 为可移植的程序起见,栈的动态分配操作是不被鼓励的!
@interface TestObject()@end
@implementation TestObject
- (void)testMethodWithName:(NSString *)name {//方法参数name是一个指针,指向传入的参数指针所指向的对象内存地址。name是在栈中//通过打印地址可以看出来,传入参数的对象内存地址与方法参数的对象内存地址是一样的。但是指针地址不一样。NSLog(@"name指针地址:%p, name指针指向的对象内存地址:%p", &name, name);//*person 是指针变量,在栈中, [Person new]是创建的对象,放在堆中。//person指针指向了[Person new]所创建的对象。//那么[Person new]所创建的对象的引用计数器就被+1了,此时[Person new]对象的retainCount为1Person *person = [Person new];
}

2.堆区

就是那些由newallocmallocrealloc创建的对象所分配的内存块,它们的释放系统不会主动去管,由我们的开发者去告诉系统什么时候释放这块内存(一个对象引用计数为0时系统就会回销毁该内存区域对象)。一般一个 new 就要对应一个 release。在ARC下编译器会自动在合适位置为OC对象添加release操作。会在当前线程Runloop退出或休眠时销毁这些对象,MRC则需程序员手动释放。堆可以动态地扩展和收缩。

注意:全局区又可分为未初始化全局区:bss段 和 初始化全局区:data段。

优点:

  • 灵活方便,数据适应面广泛,但是效率有一定降低。[顺序随意]
  • 堆是函数库内部数据结构,不一定唯一。
  • 不同堆分配的内存无法互相操作。
  • 堆空间的分配总是动态的。
  • 虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请内存,释放内存匹配是良好程序的基本要素。
//alloc是为Person对象分配内存,init是初始化Person对象。本质上跟[Person new]一样。
Person *person = [[Person alloc] init];

3.常量区

存放常量(整型、字符型,浮点型,字符串等),整个程序运行期不能被改变

常量:

已初始化的全局变量
已初始化的静态变量

  • 空间由系统管理,生命周期为整个程序运行期

4.静态区

全局变量和静态变量被分配到同一块内存中,在以前的 C 语言中,全局变量又分为初始化的和未初始化的(初始化的全局变量和静态变量在一块区域,未初始化的全局变量与静态变量在相邻的另一块区域,同时未被初始化的对象存储区可以通过 void* 来访问和操纵,程序结束后由系统自行释放),在 C++ 里面没有这个区分了,他们共同占用同一块内存区。

  • 内存空间也是由系统管理 -->程序启动时开辟程序结束时回收,程序执行期间一直存在。
  • static修饰的变量仅执行一次,生命周期为整个程序运行期

5.代码区

存放函数的二进制代码。

NSString *string1;//string1 这个NSString 类型的指针,未初始化存在于<全局区>的<BSS区>NSString *string2 = @"1234";//string2 这个NSString类型的指针,已初始化存在与<全局区>的<data数据区>,@“1234”存在与堆区,因为@代表了对象。 static NSString *string3;//string3 这个NSString 类型的指针存在于<全局区>的<BSS区>static NSString *string4 = @"1234";//string4 这个NSString类型的指针存在与<全局区>的<data数据区>,@“1234”存在与堆区,因为@代表了对象。stiring2和string4的值地址是一样的static const NSString *string5 = @"654321";//const 修饰后  string5不能修改值。 其他的与string4一样- (void)test {int  a;//a这个int类型的变量 是存在与<栈区>的
a = 10;//10这个值是存在与 <常量区>的NSStirng *str;//str这个NSString类型的指针 存在于<栈区>
str = @“1234”;//@“1234”这个@对象存在于 <堆区>static NSString *str1;//str1这个NSString类型的指针 存在于<全局区>的<BSS区>
static NSString *str2 = @"4321"; //str2这个NSString类型的指针 存在于<全局区>的<data区>NSString *str3;//str3这个NSString类型的指针 存在于<栈区>
str3 = [[NSString alloc] initWithString:@"1234"];//[[NSString alloc]initWithString:@"1234"]这个对象 存在于<堆区>
}

二、static、extern、const比较

1.static静态变量

静态变量有两种

static NSString *name;
  • 全局静态变量

优点:不管对象方法还是类方法都可以访问和修改全局静态变量,并且外部类无法调用静态变量,定义后只会指向固定的指针地址,供所有对象使用,节省空间。
缺点:存在的生命周期长,从定义直到程序结束。
建议:从内存优化和程序编译的角度来说,尽量少用全局静态变量,因为存在的生命周期长,一直占用空间。程序运行时会单独加载一次全局静态变量,过多的全局静态变量会造成程序启动慢。

  • 局部静态变量

优点:定义后只会存在一份值,每次调用都是使用的同一个对象内存地址的值,并没有重新创建,节省空间,只能在该局部代码块中使用。
缺点:存在的生命周期长,从定义直到程序结束,只能在该局部代码块中使用。
建议:局部和全局静态变量从本根意义上没有什么区别,只是作用域不同而已。如果值仅一个类中的对象和类方法使用并且值可变,可以定义全局静态变量,如果是多个类使用并可变,建议值定义在model作为成员变量使用。如果是不可变值,建议使用宏定义。

2.extern全局变量

全局变量有两种

//.m中要定义
NSString *name;//.h中同时要定义
extern NSString *name;
  • 对内的全局变量:没有用extern在.h中修饰的变量,仅定义在.m中让该变量只能在该类使用

优点:不管对象方法还是类方法都可以访问和修改全局静态变量,并且外部类无法调用静态变量,定义后只会存一份值,供所有对象使用,节省空间。跟全局静态变量一样,只是少了static修饰少了static特性。
缺点:存在的生命周期长,从定义直到程序结束。
建议:都跟全局静态变量都一样了,还需要用对内的全局变量吗?不用extern修饰就少了extern的特性,还不如用全局静态变量,至少能明确的知道static是对内使用的。

  • 外部全局变量:除了该类,其他文件也可以访问该变量

优点:除了该类,其他文件也可以访问该变量。
缺点:存在的生命周期长,从定义直到程序结束。并且外部可以修改其值,出现错误不容易定位。
建议:使用全局变量的原因就在于其对外的特性,但是其使用的方便性没有使用model的属性或宏来得方便。程序启动的时候会单独加载全局变量,同理与全局静态变量,少使用。

全局静态变量与全局变量 其实本质上是没有区别的,只是存在修饰区别,一个static让其只能内部使用,一个extern让其可以外部使用。

3.const常量

不同于变量,常量的值是固定不可变的,一般用于只读值。
优点:只可以读取值,不能修改。一般用于接口或者文字显示这种固定值。添加extern可以对外全局常量,任意位置都可以访问。
缺点:存在的生命周期长,从定义直到程序结束。需要在.h .m中分别定义代码较多。
建议:良好的编码习惯而言,少使用宏,多使用常量。因为常量声明是有明确类型的,而宏只是替换并不能进行类型判断。不够严谨。

//.h中定义extern
extern NSString *const name;
//.m中定义值
NSString *const name = @"123";//const声明部位不同,意义也不同。const定义的是其右边整体不可变。//*const name1定义的是 name1 不可变。 name1是指针。
//因此 不能通过修改name1而指向其他值。常规的const使用这个方法定义不可修改的值
NSString *const name1 = @"456";//const * name定义的是 * name不可变, 而*name指向的是@"789",
//也就是说@"789"这个内存地址的值不可变为其他值。
NSString const * name2 = @"789";
//但name指针可以指向其他值,所以该定义方式无法保证值的唯一性。
NSString *newName = @"222";
name2 = newName;

三、注意

  • 当一个 app 启动后,代码区、常量区、全局区大小就已经固定,因此指向这些区的指针不会产生崩溃性的错误。而堆区和栈区是时时刻刻变化的(堆的创建销毁,栈的弹入弹出),所以当使用一个指针指向这个区里面的内存时,一定要注意内存是否已经被释放,否则会产生程序崩溃(也即是野指针报错)。
  • 在 iOS 中,堆区的内存是应用程序共享的,堆中的内存分配是系统负责的。

【iOS】—— 内存的五大分区相关推荐

  1. iOS——内存分配与分区

    这篇文章依次介绍一下iOS中内存的分配与分区. 1.RAM & ROM 存储器(Memory)是计算机系统中的记忆设备,用来存放程序和数据. iOS的存储器包括RAM(random acces ...

  2. C语言学习笔记:内存的五大分区

    在C语言中,进程可在内存中分别存入五大分区: 1.text:也称为代码段,其中主要用于存放二进制指令.常量.被const修饰过的初始化过的全                      局变量.静态局部 ...

  3. iOS内存分配与五大区域

    目录: 参考的博客: iOS内存的五大区域 : 栈区(stack) 堆区(heap): 全局区(又称静态区)(static): 文字常量区: 程序代码区: Allocations模版: 虚拟内存简介: ...

  4. 【iOS】内存五大分区

    文章目录 五大分区 栈区 堆区 常量区 静态区 代码区 如何查看一个对象在堆区 / 栈区 注意 说到内存分区,这里的内存指的就是RAM(random access memory). 内存分为五个区:栈 ...

  5. iOS内存扫描工具实现

    由于不能告诉你的原因,我需要一个iOS下的,可以在指定App的内存中搜索字符串的工具. 找了一圈,发现一个比较接近的开源项目:rxmemscan,但是不支持搜索字符串,遂 修改 学习了一番. 又,修改 ...

  6. Objective-C runtime机制(5)——iOS 内存管理

    概述 当我们创建一个对象时: SWHunter *hunter = [[SWHunter alloc] init]; 上面这行代码在栈上创建了hunter指针,并在堆上创建了一个SWHunter对象. ...

  7. iOS 开发:彻底理解 iOS 内存管理(MRC 篇)

    本文首发于我的个人博客:「程序员充电站」 文章链接:「传送门」 本文更新时间:2021年08月17日17:11:59 本文是 「iOS 开发:彻底理解 iOS 内存管理」系列的「MRC 篇」. 用来对 ...

  8. iOS内存缓存和磁盘缓存的区别

    缓存分为内存缓存和磁盘缓存两种,其中内存是指当前程序的运行空间,缓存速度快容量小,是临时存储文件用的,供CPU直接读取,比如说打开一个程序,他是在内存中存储,关闭程序后内存就又回到原来的空闲空间:磁盘 ...

  9. 【iOS开发】—— iOS内存管理

    文章目录 1. iOS内存分配区域 1.1 栈区 1.2 堆区 1.3 常量区 1.4 全局区/静态区 1.4.1 static静态变量 1.4.2 extern全局变量 1.5 代码区 2. iOS ...

最新文章

  1. Yunyang tensorflow-yolov3 voc_train.txt以及voc_test.txt引用的路径位置
  2. Serval and Bus
  3. 好代码是管出来的——使用Jenkins搭建CI服务器
  4. 这几个公众号隐藏着暴富的秘诀
  5. PAT甲级1056(queue的用法)
  6. latex 图片缩小指定比例
  7. 3D屏保:魔方2.0版本
  8. 用批处理文件阻止win10强制更新
  9. Gameloft的移动游戏王者之路
  10. Cubase10自编曲平台,享受音乐带来的快乐!
  11. Kafka学习整理三(borker(0.9.0及0.10.0)配置)
  12. 【爱情叙记】--刚闹完别扭
  13. Android 应用的逆向和审计
  14. TWS耳机哪款好用?2022TWS耳机推荐
  15. 北大四大“疯人院”到底有多牛?天才、怪才在这儿遍地都是!
  16. web前端实训作业 html+css+javascript 水果超市网页设计实例 企业网站制作
  17. tensorflow 参数clipping
  18. Fabric实战(四)-多机部署fabric网络-solo
  19. 关于for i in list1: 中i变量的内容
  20. 把漫画浏览器的离线下载的功能给实现了一下

热门文章

  1. 三亚旅游攻略!三亚亚龙湾五号度假别墅酒店攻略
  2. Excel里半勾的打法
  3. ExcelToDatabase:批量导入Excel文件到MySQL/Oracle/SQL Server数据库的自动化工具
  4. 大学计算机上机实验指导与测试pdf,大学计算机基础上机指导与测试-王瑞祥主编.pdf...
  5. php 获取域名前缀,蓝奏批量自定义域名前缀替换php源码
  6. linux 重定向偶尔失效,Linux crontab 输出重定向不生效问题解决
  7. 优信年营收16亿:亏损3亿 已与蔚来资本及58集团签署股权协议
  8. 100小时学SAP SD后台配置清单
  9. MACD技术的高级应用--MACD与波浪
  10. calc()函数及vmin,vmax,vh,vw的认识,在family里的实战运用