【iOS】内存管理五大区

news2024/11/15 23:20:26

参考博客:iOS内存管理学习第一篇-内存五大区
3.1 OC特性之 内存五大区域

1. 简述

程序要想执行,第一步就需要 被加载到内存中
内存五大区域: 栈区,堆区,BSS段(静态区),常量区(数据段),代码段.

  1. 栈区(stack)由编译器自动分配并释放,存放函数的参数值,局部变量等。栈是系统数据结构,对应线程/进程是唯一的。iphone的栈区只有512K,其操作方式类似于数据结构中的栈
    优点:快速高效
    缺点:有限制,数据不灵活[先进后出]
  2. 堆区(heap)由程序员分配和释放,如果程序员不释放,程序结束后,可能由操作系统回收。类似于链表
    优点:灵活方便,数据适应面广泛
    缺点:效率有一定降低
  3. BSS段(静态区)全局变量和静态变量的存储区,程序结束后有系统释放。
  4. 常量区存放常量字符串,程序结束后由系统释放。
  5. 代码区,存放函数的二进制代码,程序结束后由系统释放。

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 栈区中的保存(栈区的职责/存储的内容)

  • 局部变量
  • 方法实参(eg:在main函数中,调用方法,方法中的实参)

2.1.2 栈区的特点

  • 存储空间有限 . iphone的栈区大小只有512k(默认) ,非常有限
  • 连续性 . 栈区的地址是连续的
  • 地址分配从大到小. 栈区地址按照分配的顺序,由大到小顺序排列
  • 访问速度快.
  • 系统管理. (栈区的内存由系统管理)

2.1.3 其他

如果在程序中调用方法,会开启一个 " 栈帧 ".(这个栈帧可以理解为也是一块连续的区域)
栈帧的地址与之前的局部变量的地址不是连续的栈帧中记录实参地址,
以及方法内部的局部变量。方法执行完毕后,栈帧销毁(弹栈)
<<<这样每次执行完毕后,都弹栈释放内存,这样就会始终保证栈区占用的内存不会特别大>>
so-课外话->我们在开发的时候,如果每个方法都写的很短,同时每个方法声明的变量都很少.
这样做一定会节约内存

总结

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

  • 开启栈帧
  • 保存实参
  • 保存局部变量
  • 方法完成后弹栈,销毁栈帧,释放空间

2.2 堆区

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

2.2.1 堆区中保存:

  • 使用 new \alloc\init 方法创建的对象保存在堆区
  • 被创建对象的所有成员变量保存在堆区中

在开发 OC 程序的时候,程序员通常不需要考虑内存释放的工作。
但是如果在 OC 的代码中,如果使用到 C 语言分配空间的函数,则需要考虑释放内存

  1. 堆区的大小由系统决定,包括:系统内存/磁盘交换空间…
  2. 系统使用链表来管理堆区中的内存分配情况
  3. {程序员只需要负责堆区中内存的分配和释放工作}

2.2.2 堆区的特点

  • 所有程序共享
  • 存储大数据
  • 程序员管理: 堆区的内存需要程序员管理
  • 不连续: 堆区的地址是不连续的
  • 速度没有栈区快: 堆区的访问速度没有栈区快,因为我们要访问堆区中创建对象的属性, 必须先需要通过变量找到栈区的地址,再通过地址定位到到堆区中的某一个位置, 只有找个这个位置之后,我们才可以访问到存储到这个对象中属性对应的数值.由于有了 这个地址寻找的过程,所有速度没有栈区的快.

3. 全局变量、静态变量和常量

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

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

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

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

在Xcode13.3.1中,未初始化的全局变量和静态变量储存在静态区(.BSS段),初始化的全局变量和静态变量储存在数据区(.data段)。
需要注意的是,数据段通常是指静态区的一个子区域。在不同的系统和编译器中,这些术语可能有不同的定义和使用方式。有时候,数据段和静态区这两个术语也会被用来表示相同的内存区域。

验证:

验证代码:

// 设置两个全局变量,一个初始化,一个不初始化
int num1 = 1;
int num2;

int main(){
    @autoreleasepool {
        NSLog(@"num1 pointer = %p", &num1);
        NSLog(@"num2 pointer = %p", &num2);
        
        // 初始化num2
        num2 = 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);
    }
}

验证结果:

在这里插入图片描述

可知:

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

3.1.2 常量保存的内存区域

常量保存在常量区。

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

// 设置两个全局变量,一个初始化,一个不初始化
int num1 = 1;
int num2;

int main(){
    @autoreleasepool {
        NSLog(@"num1 pointer = %p", &num1);
        NSLog(@"num2 pointer = %p", &num2);
        
        // 初始化num2
        num2 = 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);
    }
}

结果:
在这里插入图片描述

可知:

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

3.2 静态区

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

3.3 常量区

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

4. TaggedPointer

以下是三种系统针对内存管理优化做出的方案
在这里插入图片描述

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

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

这是使用TaggedPointer的大致范围,如图
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/757655.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手写Spring框架---MVC实现

目录 预备 自研框架MVC的实现 MVC架构草图&#xff1a; 大致流程 实现思路 自定义注解 JavaBean 请求的拦截-建立DispatcherServlet 责任链处理请求 RequestProcessor矩阵 Render矩阵 预备 在DispatcherServlet&#xff1a; 解析请求路径和请求方法依赖容器&#xf…

最全的 Spring 依赖注入方式,你都会了吗?

Spring 正如其名字&#xff0c;给开发者带来了春天&#xff0c;Spring 是为解决企业级应用开发的复杂性而设计的一款框架&#xff0c;其设计理念就是&#xff1a;简化开发。 Spring 框架中最核心思想就是&#xff1a; IOC&#xff08;控制反转&#xff09;&#xff1a; 即转移…

ChatGPT 最佳实践指南之:使用外部工具

Use external tools 使用外部工具 Compensate for the weaknesses of GPTs by feeding them the outputs of other tools. For example, a text retrieval system can tell GPTs about relevant documents. A code execution engine can help GPTs do math and run code. If a …

45、Spring Boot自动配置原理

Spring Boot自动配置原理 lmport Configuration Spring spi 自动配置类由各个starter提供&#xff0c;使用Configuration Bean定义配置类&#xff0c;放到META-INF/spring.factories下使用Spring spi扫描META-INF/spring.factories下的配置类使用lmport导入自动配置类

通讯录管理系统--进阶(动态开辟内存+保存数据到文件)

文章目录 动态开辟内存优化改进通讯录类型改进初始化通讯录函数改进添加联系人的函数增加销毁通讯录信息的函数 保存数据到文件优化保存通讯录数据到文件读取数据到通讯录 完整的代码展示 在 C语言实现通讯录的所有基本功能详细代码分析中&#xff0c;我们已经实现了通讯录的基…

Linux系统编程:文件系统和inode

目录 一. 磁盘的结构和读写数据的方式 1.1 磁盘级文件和内存级文件 1.2 磁盘的物理结构 1.3 访问磁盘数据的方式 二. 磁盘文件系统 2.1 磁盘的分区管理方法 2.2 文件名和inode的关系 三. 结合文件系统对文件创建和删除的相关问题的理解 3.1 文件创建时操作系统进行的工…

如何给合宙ESP32-C3刷写arduino固件,arduinoIDE的配置,测试代码

视频教程 https://github.com/Yu-1120/ESP32-C3 资料下载地址 合宙ESP32-C3刷写arduino固件 然后点击安装就可以了 arduino-IDE的配置 我用的版本&#xff1a;2.1.1&#xff08;版本不对也多大没关系&#xff09; 下载安装 选择 ESP32C3 Dev Module 安装环境 配置环境&am…

二十六、传输层协议(下)

一、滑动窗口 刚才我们讨论了确认应答策略&#xff0c;对每一个发送的数据段&#xff0c;都要给一个ACK确认应答. 收到ACK后再发送下一个数据段。这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候. 既然这样一发一收的方式性能较低, 那么我们一次发送…

snpEff注释结果解读

目录 1.帮助文档 1.1 常用参数 2. 命令的用法&#xff1a; 3. 结果文件解读 4. SNP下游的分析 利用snpEff软件对 snp.vcf &#xff08;利用gatk软件calling-snp&#xff09;进行注释&#xff0c;运行下述命令&#xff1a; ## 构建好物种的数据库 java -jar /opt/snpEff/s…

基于Spring Boot的扶贫助农商城系统设计与实现(Java+spring boot+MySQL+VUE)

获取源码或者论文请私信博主 演示视频&#xff1a; 基于Spring Boot的扶贫助农商城系统设计与实现&#xff08;Javaspring bootMySQLVUE&#xff09; 使用技术&#xff1a; 前端&#xff1a;html css javascript jQuery ajax thymeleaf 微信小程序 后端&#xff1a;Java spr…

QTranslator语言转换

//appname的格式 例如通常为&#xff08;QQ为应用的名称&#xff09; QQ_en.ts或QQ_zh_CN.ts QString qmName"zh_CN"; QTranslator trans ; QString qm QString(":/translatoin/qt/appname_%1.qm").arg(qmName); auto ret trans.load(qm); Q_UNUSED(ret)…

CSS高级特性

1.CSS复合选择器 CSS复合选择器&#xff1a;复合选择器是由两个或多个基础选择器通过不同的方式组合而成的 1.1 标签指定式选择器&#xff1a;又称交集选择器&#xff0c;由两个选择器构成&#xff0c;其中第一个选择器为标记选择器&#xff0c;第二个为class选择器或id选择器…

【Spring core学习一】简单认识Spring是什么?

目录 1、为什么要学习Spring&#xff1f; 2、Spring是什么&#xff1f; 1、IoC是什么&#xff1f; 2、进一步通过代码演示理解IoC 3、怎么理解容器&#xff1f; 4、知道DI与IoC的区别&#xff1f; 1、为什么要学习Spring&#xff1f; 我们常说的Spring 指的是 Spring Fra…

地平线旭日x3派40pin引脚控制,点亮小灯,控制舵机

地平线旭日x3派40pin引脚控制&#xff0c;点亮小灯&#xff0c;控制舵机 引脚对照表点亮RGB小灯安装旭日X3派WiringPi使用WiringPi点亮RGB小灯使用软件PWM功能 官方用户手册中只有python控制教程&#xff0c;没有c语言控制教程。且官方的教程中并没有软件pwm功能。本教程在开发…

Linux——动静态库的制作和使用(实操+代码+原理介绍)

动静态库的制作和使用 1️⃣.动静态库介绍&#x1f3c0;静态库⚽️动态库&#x1f3c8;区别&#x1f3d0;使用动态库的优点包括&#xff1a;&#x1f3c9; 使用静态库的优点包括&#xff1a; 2️⃣静态库的制作&#x1f34a;Q:库文件能不能有main()函数&#xff1f;&#x1f34…

imazing是什么软件?2023年imazing官网中文版下载

最近很小伙们&#xff0c;咨询兔八哥&#xff0c;imazing是什么软件&#xff1f;&#xff0c;今天兔八哥爱分享整理一下imazing到底是什么软件&#xff1f;好用吗&#xff1f; imazing是一款iOS设备管理软件,借助 iMazing 的独有 iOS 备份技术&#xff08;无线、隐私和自动&am…

地震正演基础知识

文章目录 地震正演1. 地震正演基础知识1.1 地震波1.2 波动方程1.3 有限差分方法1.4 边界条件1.5 记录数据 2. 公式2.1 泰勒级数回顾2.2 二维声波方程&#xff08;连续的偏微分方程&#xff09;2.2.1 二维声波方程&#xff08;连续的偏微分方程&#xff09;2.2.2 离散化二维声波…

【C++】vector模拟实现

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

Netty 为什么有如此高的性能?

文章首发地址 Netty高性能的三个主题 I/O传输模型&#xff1a;用什么样的通道将数据发送给对方&#xff0c;是BIO、NIO还是AIO&#xff0c;I/O传输模型在很大程度上决定了框架的性能。数据协议&#xff1a;采用什么样的通信协议&#xff0c;是HTTP还是内部私有协议。协议的选…

1767_Perl中的全词匹配

全部学习汇总&#xff1a; GreyZhang/perl_basic: some perl basic learning notes. (github.com) 当我在上一家公司工作的时候遇到过一个问题&#xff0c;为了解决软件接口的冲突我们需要把一个软件工程中的所有变量全都修改加一个前缀。我觉得用Perl处理是一个很好的注意&…