首页 >> 大全

【iOS】内存管理五大区

2023-08-27 大全 23 作者:考证青年

参考博客:iOS内存管理学习第一篇-内存五大区

3.1 OC特性之 内存五大区域

1. 简述

程序要想执行,第一步就需要 被加载到内存中

内存五大区域: 栈区,堆区,静态区,常量区,代码段.

栈区(stack)由编译器自动分配并释放,存放函数的参数值,局部变量等。栈是系统数据结构,对应线程/进程是唯一的。的栈区只有512K,其操作方式类似于数据结构中的栈

优点:快速高效

缺点:有限制,数据不灵活[先进后出]堆区(heap)由程序员分配和释放,如果程序员不释放,程序结束后,可能由操作系统回收。类似于链表

优点:灵活方便,数据适应面广泛

缺点:效率有一定降低静态区,全局变量和静态变量的存储区,程序结束后有系统释放。常量区存放常量字符串,程序结束后由系统释放。代码区,存放函数的二进制代码,程序结束后由系统释放。 2. 堆区与栈区

int main(int argc, const char * argv[]) {// 局部变量是保存在栈区的// 栈区变量出了作用域之后,就会被销毁NSInteger i = 10;NSLog(@"%zd", i);// 赋值语句右侧,使用 new\alloc\init 方法创建的对象是保存在堆区的// xinge 变量中,记录的是堆区的地址// 在 OC 中,有一个内存管理机制,叫做 `ARC`,可以自动管理 OC 代码创建对象的生命周期// 因此,在开发 OC 程序的时候,程序员通常不需要考虑内存释放的工作LJXPerson *xinge = [LJXPerson new];NSLog(@"%@", xinge);return 0;
}

2.1 栈区

栈区 (stack [stæk]) : 由编译器自动分配释放

2.1.1 栈区中的保存(栈区的职责/存储的内容) 2.1.2 栈区的特点 2.1.3 其他

如果在程序中调用方法,会开启一个 " 栈帧 ".(这个栈帧可以理解为也是一块连续的区域)

栈帧的地址与之前的局部变量的地址不是连续的栈帧中记录实参地址,

以及方法内部的局部变量。方法执行完毕后,栈帧销毁(弹栈)

我们在开发的时候,如果每个方法都写的很短,同时每个方法声明的变量都很少.

这样做一定会节约内存

总结

调用方法时栈区的工作原理

2.2 堆区

堆区 (heap [hiːp]): 由程序员分配释放,若程序员不释放,会出现内存泄漏

2.2.1 堆区中保存:

在开发 OC 程序的时候,程序员通常不需要考虑内存释放的工作。

但是如果在 OC 的代码中,如果使用到 C 语言分配空间的函数,则需要考虑释放内存

堆区的大小由系统决定,包括:系统内存/磁盘交换空间…系统使用链表来管理堆区中的内存分配情况{程序员只需要负责堆区中内存的分配和释放工作} 2.2.2 堆区的特点 3. 全局变量、静态变量和常量 3.1 全局变量/静态变量/常量保存的内存区域

开发要让变化控制在有限的范围内

3.1.1 全局变量/静态变量保存的内存区域

这一部分因编译器、操作系统和具体的平台而有所不同。某些编译器和平台可能对内存布局和段的使用有自己的优化策略。因此,具体情况可能会有所变化,需要查看编译器和平台的文档以了解详细信息。

在.3.1中,未初始化的全局变量和静态变量储存在静态区(.BSS段),初始化的全局变量和静态变量储存在数据区(.data段)。

需要注意的是,数据段通常是指静态区的一个子区域。在不同的系统和编译器中,这些术语可能有不同的定义和使用方式。有时候,数据段和静态区这两个术语也会被用来表示相同的内存区域。

验证:

验证代码:

// 设置两个全局变量,一个初始化,一个不初始化
int num1 = 1;
int num2;int main(){@autoreleasepool {NSLog(@"num1 pointer = %p", &num1);NSLog(@"num2 pointer = %p", &num2);// 初始化num2num2 = 2;NSLog(@"init num2 pointer = %p", &num2);// 设置两个静态变量,一个初始化,一个不初始化static int sNum1 = 1;static int sNum2;NSLog(@"sNum1 pointer = %p", &sNum1);NSLog(@"sNum2 pointer = %p", &sNum2);sNum2 = 2;NSLog(@"init sNum2 pointer = %p", &sNum2);}
}

验证结果:

_iphone内存管理机制_ios内存区域

可知:

静态变量与全局变量未初始化储存在静态区(.BSS段),地址连续;静态变量与全局变量初始化储存在数据区(.data段),地址连续;静态变量与全局变量初始化前后储存地址不变,说明其储存区域一开始便决定,之后不再改变;静态区(.BSS段)与数据区(.data段)地址连续,其划分并不严格(其划分应该是动态的),完全可以当作一个区域。 3.1.2 常量保存的内存区域

常量保存在常量区。

给前面的验证代码加一个常量:

// 设置两个全局变量,一个初始化,一个不初始化
int num1 = 1;
int num2;int main(){@autoreleasepool {NSLog(@"num1 pointer = %p", &num1);NSLog(@"num2 pointer = %p", &num2);// 初始化num2num2 = 2;NSLog(@"init num2 pointer = %p", &num2);// 设置两个静态变量,一个初始化,一个不初始化static int sNum1 = 1;static int sNum2;NSLog(@"sNum1 pointer = %p", &sNum1);NSLog(@"sNum2 pointer = %p", &sNum2);sNum2 = 2;NSLog(@"init sNum2 pointer = %p", &sNum2);// 常量const int cNum = 3;NSLog(@"cNum pointer = %p", &cNum);}
}

结果:

可知:

常量与静态变量、全局变量不在一个区域保存,常量保存在常量区。 3.2 静态区

储存静态变量和全局变量,是否在一开始便初始化决定它们储存在.BSS段还是.data段,一经决定不再更改。

3.3 常量区

储存常量,不论是否初始化。

4.

以下是三种系统针对内存管理优化做出的方案

首先就是我们说到的,推荐大家去看下官方提供的视频WWDC 2020,里面有详细解释为什么会使用到,总结以下几点

专门用来存小数据 ,通过高位直接判断数据类型,例如,,g字符串小对象并没有进堆区,值直接存在指针,而不是想常规数据,指针存地址,所以实际上它不是一个对象,只是一个普通变量而已,没存在堆中,自然也不需要和free内存读取3倍效率,创建速度快106倍

这是使用的大致范围,如图

关于我们

最火推荐

小编推荐

联系我们


版权声明:本站内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 88@qq.com 举报,一经查实,本站将立刻删除。备案号:桂ICP备2021009421号
Powered By Z-BlogPHP.
复制成功
微信号:
我知道了