【iOS】内存管理五大区

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

1. 简述

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

  1. 栈区(stack)由编译器自动分配并释放,存放函数的参数值,局部变量等。栈是系统数据结构,对应线程/进程是唯一的。iphone的栈区只有512K,其操作方式类似于数据结构中的栈
    优点:快速高效
    缺点:有限制,数据不灵活[先进后出]
  2. 堆区(heap)由程序员分配和释放,如果程序员不释放,程序结束后,可能由操作系统回收。类似于链表
    优点:灵活方便,数据适应面广泛
    缺点:效率有一定降低
  3. 静态区,全局变量和静态变量的存储区,程序结束后有系统释放。
  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的大致范围,如图
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

React 安装 报错“Modal不能用作jsx组件”

提示 &#xff1a;‘Modal’ cannot be used as a JSX component. 原因&#xff1a;可能导致是类似antd组件报错 要确认react ts 版本是否适配 解决方法&#xff1a; 第一步&#xff1a;查看代码中的 package.json 文件 查看 typescript 与 types/react 第二步&#xff1a;查…

Shuffle简单理解

map的结果本身是无序的&#xff0c;但是map输出的结果有序 mapper和reduce是不同的机器&#xff0c;进行了网络传输&#xff0c;所以存在数据拷贝 第二次排序&#xff0c;是将每个reduce对应的task进行排序&#xff0c;然后再进入reduce maptask运行结束&#xff0c;每个mask块…

详解Windows安装分布式版本控制系统git

文章目录 前言下载安装相关链接 前言 git是一个分布式版本控制软件&#xff0c;最初由Linux创作者Linus Torvalds创作&#xff0c;并于2015年以GPL许可协议发布。git易于学习&#xff0c;占用空间小&#xff0c;性能却快如闪电&#xff0c;可以快速、 高效的管理从小到大的项目…

Java设计模式-责任链(Chain of Responsibility)模式

介绍 Java责任链&#xff08;Chain of Responsibility&#xff09;设计模式是指很多处理对象构成一个链&#xff0c;链中前一个对象指向后一个对象。请求在链中传递&#xff0c;一个请求可以被一个或者多个对象处理。调用方&#xff08;即客户端&#xff09;不知道请求会被链中…

DT灯光基础(辉光 雾 阴影 渲染选项)

点光源 不能宣染&#xff0c;换个版本。不能正常预览 聚光灯 t 手柄 挡光版 平行光阴影 光线追踪阴影 没有看见阴影 灯光使用贴图 环境光 不进行渲染物体 不渲染阴影 接收阴影 不反射 可以看到反射 没有反射了 灯光链接 取消灯照 灯光雾 辉光 变化不明显

瑞芯微|如何让拥有双网口的Linux设备实现数据包转发?

本文主要讲解如何&#xff0c;解决基于3568实现双网口互通问题。 一、组网 如下图所示&#xff1a; rk3568自带2个千兆以太口&#xff0c;对应网卡名称为&#xff1a;eth0、eth1pc1和pc2分别连接这2个网口pc1与eth0连接&#xff0c;网段&#xff1a;192.168.30.0pc2与eth1连…

PostgreSQL 的就业前景如何?

PostgreSQL的就业前景非常广阔&#xff0c;它是一种功能强大、可靠且开源的关系型数据库管理系统。以下是说明PostgreSQL就业前景的几个关键点&#xff1a; 1.高需求&#xff1a;随着企业和组织对数据存储和管理的需求不断增长&#xff0c;对数据库专业人员的需求也在持续上升…

喜讯!旭帆科技成功入驻“科大硅谷”!

2023年7月&#xff0c;安徽旭帆信息科技有限公司&#xff08;以下简称“旭帆科技”&#xff09;成功入驻“科大硅谷”&#xff0c;成为合肥城市发展新引擎、科创生态集群企业队伍中的一员。 “科大硅谷”项目建设总投资约75.82亿&#xff0c;共计17.37平方公里&#xff0c;是聚…

idea手动导入了包但编译运行还是报找不到xxx.jar包的问题

1、先把jar包放目录下并add as libary 2、在pom.xml中加入 <!--添加的本地的外部jar包依赖--><dependency><!--groupId、artifactId、version为自定义&#xff0c;groupId与artifactId但是不能重名--><groupId>JNative</groupId><artifactId…

如何设计光场2.0(聚焦型光场相机)系统参数

1. 系统参数设计 目前的硬件系统的现状&#xff1a;主透镜50mm&#xff0c;MLA&#xff1a;15*15&#xff0c;d0.5mm&#xff0c;f15mm&#xff0c;s4.8um 开普勒型光场系统&#xff1a; 首先我们需要确定系统的M&#xff0c;M参数表示单个位置的点能被多少个小微透镜成像&am…

分享一个唯美雪花界面

先看效果&#xff1a; 再看代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>雪</title><meta name"viewport" content"widthdevice-width, initial-scale1&…

【3-D深度学习:肺肿瘤分割】创建和训练 V-Net 神经网络,并从 3D 医学图像中对肺肿瘤进行语义分割研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f308;4 Matlab代码实现 &#x1f4a5;1 概述 使用3D深度学习进行肺肿瘤分割是一种有前景的研究方向。V-Net是一种常用的3D神经网络&#xff0c;特别适用于医学图像分割任务。下面是一个基本…

【Web安全】小白怎么快速挖到第一个漏洞,src漏洞挖掘经验分享,绝对干货!

src漏洞挖掘经验分享 – 掌控安全以恒 一、公益src 公益src是一个白帽子提交随机发现的漏洞的品台&#xff0c;我们可以把我们随机发现或者是主动寻找到的漏洞在漏洞盒子进行提交。 在挖掘src的时候不能越红线&#xff0c;一般情况下遇到SQL注入 只获取数据库名字以证明漏洞的…

android JSBridge的加载时机问题

https://github.com/lzyzsd/JsBridge 也算是比较悠久和使用了。 可供参考的android和IOS&#xff0c;以及前端的使用 https://segmentfault.com/a/1190000018208609 遇到的问题&#xff1a; 比如&#xff1a; 从前端在加载WebView的时候&#xff0c;执行了某些动作&#xff0c…

qiankun:react18主应用 + 微应用 react18 + vue3

一&#xff1a;主应用 搭建react项目 npx create-react-app react-qiankun-main安装Antd npm install antd –save在 index.js中引入 import { ConfigProvider } from "antd"; import zhCN from "antd/locale/zh_CN"; import "antd/dist/reset.css…

【C++】将类对象转换成基本数据类型

2023年7月19日&#xff0c;周三晚上&#xff1a; 今天晚上看源码的时候&#xff0c;突然在某个类里面看到了“operator bool() const;”&#xff0c;我完全想不起来这是啥意思了&#xff0c;于是今晚重新学习了一下 目录 类型转换函数的定义类型转换函数的作用 类型转换函数的…

Redis(三)存储原理与数据模型(hash冲突、渐进式rehash)

Redis系列文章 Redis&#xff08;一&#xff09;原理及基本命令&#xff08;柔性数组&#xff09; Redis&#xff08;二&#xff09;网络协议和异步方式&#xff08;乐观锁&悲观锁&#xff09; Redis&#xff08;三&#xff09;存储原理与数据模型&#xff08;hash冲突、渐…

超牛逼黑客帝国代码雨,装X必用

html 1.用法 在电脑桌面新建一个文本文档&#xff0c;然后将代码复制到文本文档里&#xff0c;再将后缀改为".html"。 2.效果图 <!DOCTYPE html> <html> <head><title>黑客帝国代码雨</title> </head><body> <can…

C++编程(四) —— OOP

文章目录 前言一、this指针二、构造和析构三、深拷贝浅拷贝浅拷贝深拷贝 编程实践 前言 什么是OOP思想&#xff1f; OOP语言的四大特征&#xff1a; 抽象&#xff0c;封装/隐藏&#xff0c;继承&#xff0c;多态 一、this指针 this指针》类》很多对象 一套成员方法是如何处…

【矩阵的基本操作】——MatLab基础

目录索引 矩阵的基本操作&#xff1a;转置&#xff1a;矩阵的拼接&#xff1a;*横拼&#xff1a;**竖拼&#xff1a;* 矩阵的索引&#xff1a;取元素&#xff1a;*end():* 取区域&#xff1a;逻辑判断&#xff1a;逻辑取值&#xff1a;find()&#xff1a; 矩阵的基本操作&#…