当前位置: 首页 > news >正文

[iOS]内存分区

[iOS]内存分区

文章目录

  • [iOS]内存分区
    • 五大分区
      • 栈区
      • 堆区
      • 全局区
      • 常量区
      • 代码区
      • 验证
      • 内存使用注意事项
      • 总结
    • 函数栈
      • 堆栈溢出
      • 栈的作用
    • 参考博客

在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域
还记得OC是C的超类
所以C的内存分区也是一样的

iOS系统中,应用的虚拟内存默认分配4G大小,但五大区只占3G,还有1G是五大区之外的内核区

上图

在这里插入图片描述

五大分区

栈区

定义

  • 栈是系统数据结构,其 对应的进程或者线程是唯一
  • 栈是 向低地址扩展 的数据结构
  • 栈是一块连续的内存区域,遵循 先进后出(FILO) 原则
  • 栈的地址空间在iOS中是以 0X7或者0X16开头
  • 栈区一般在 运行时分配

存储
栈区是由编译器 自动分配并释放 的,主要用来存储

  • 局部变量
  • 函数的参数,例如函数的隐藏参数(id self,SEL _cmd)

优缺

优点:因为栈是由编译器自动分配并释放的,不会产生内存碎片,所以快速高效

缺点:栈的内存大小有限制,数据不灵活

  • OS X(MAC上)主线程栈大小是8MB
  • iOS主线程栈大小是1MB
  • 其他线程是512KB
    在这里插入图片描述

堆区

定义

  • 堆是 向高地址扩展 的数据结构
  • 堆是 不连续 的内存区域,类似于链表结构(便于增删,不便于查询),遵循先进先出 (FIFO) 原则
  • 堆的地址空间在iOS中是以 0x6 开头,其空间的分配总是动态的
  • 堆区的分配一般是在 运行时分配

储存
堆区是由程序员动态分配和释放的,如果程序员不释放,程序结束后,可能由操作系统回收,主要用于存放

  • OC中使用alloc或者 使用new开辟空间创建对象
  • C语言中使用malloc、calloc、realloc分配的空间,需要free释放

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

缺点:需手动管理,速度慢、容易产生内存碎片
当需要访问堆中内存时,一般需要先 通过对象读取到栈区的指针地址 ,然后通过 指针地址 访问堆区

全局区

  • 全局区是编译时分配的内存空间
  • 在iOS中一般以 0x1 开头
  • 在程序运行过程中,此内存中的数据一直存在,程序结束后由系统释放,主要存放
    1. 未初始化的全局变量和静态变量,即BSS区(.bss)
    2. 已初始化的全局变量和静态变量,即数据区(.data)
      BBS:Block Started by Symbol

其中,全局变量是指变量值可以在运行时被动态修改,而静态变量是static修饰的变量,包含静态局部变量和静态全局变量

常量区

常量区(.rodata)是 编译时分配 的内存空间,在程序结束后由系统释放,主要存放

  • 已经使用了的,且没有指向的字符串常量
    字符串常量因为可能在程序中被多次使用,所以在程序运行之前就会提前分配内存

代码区

代码区是 编译时分配 主要用于存放程序运行时的代码,代码会被编译成 二进制 存进内存的

验证

口说无凭
来看看变量在内存中是如何分配的

- (void)test{NSInteger i = 123;NSLog(@"i的内存地址:%p", &i);NSString *string = @"CJL";NSLog(@"string的内存地址:%p", string);NSLog(@"&string的内存地址:%p", &string);NSObject *obj = [[NSObject alloc] init];NSLog(@"obj的内存地址:%p", obj);NSLog(@"&obj的内存地址:%p", &obj);  
}

请添加图片描述
回顾一下
0x1是内存区开头 用于存放
0x6是堆区开头 主要用于存放OC对象
0x7是栈区开头 主要存放局部变量

i 和 &string 和 &obj都属于局部变量 存在栈区
string内的@"CJL"是字符串 存常量区
对象obj存堆区
很完美

然后这个也是对的
在这里插入图片描述

内存使用注意事项

内存使用注意事项涵盖了多个方面,包括避免内存泄漏、防止野指针引用、正确处理数组边界、适当地分配和释放内存等

  1. 内存泄露
  2. 重复释放
  3. 野指针
  4. 数组越界
  5. 未初始化内存
  6. 缓冲区溢出

大小端模式

在这里插入图片描述

在地址读取时,分为大端模式与小端模式
大端模式从左向右每两位为一组读取
小端模式从右向左每两位为一组读取

iOS与macOS 均是小端模式

总结

一个程序在内存上由BSS段、data段、text段三个组成的。在没有调入内存前,可执行程序分为代码段、数据区和未初始化数据区三部分

BSS段:(Block Started by Symbol)
通常是指用来存放程序中未初始化的全局变量的一块内存区域,属于静态内存分配。BSS段的内容并不存放在磁盘上的程序文件中。原因是内核在程序开始运行前将它们设置为0,需要存放在程序文件中的只有正文段和初始化数据段。text段和data段在编译时已经分配了空间,而BSS段并不占用可执行文件的大小,它是由链接器来获取内存的。

数据段:(data segment)
通常是指用来存放程序中已初始化的全局变量的一块内存区域,属于静态内存分配。总结为:初始化的全局变量和静态变量在已初始化区域,未初始化的全局变量和静态变量在BSS区。

代码段:(code segment/text segment)
通常是指用来存放程序执行代码的一块内存区域。该区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。

堆(heap):
用于动态分配内存,位于BSS和栈中间的地址区域,由程序员申请分配和释放。堆是从低地址位向高地址位增长,采用链式存储结构。频繁的malloc/free造成内存空间的不连续,会产生碎片。当申请堆空间时库函数是按照一定的算法搜索可用的足够大的空间,因此堆的效率比栈要低的多。注:与数据结构中的堆不是一个概念,但堆的分配方式类似于链表。

栈(stack):
由编译器自动释放,存放函数的参数值、局部变量等。每当一个函数被调用时,该函数的返回类型和一些调用的信息被存放到栈中,这个被调用的函数再为它的自动变量和临时变量在栈上分配空间。每调用一个函数一个新的栈就会被使用。栈区是从高地址位向低地址位增长的,是一块连续的内存区域,最大容量是由系统预先定义好的,申请的栈空间超过这个界限时会提示溢出。

堆和栈的区别在于

1)管理方式:栈由编译器自动管理,无需人为控制。而堆释放工作由程序员控制,容易产生内存泄漏(memory leak)。
2)空间大小:在32位系统下,堆内存可以达到4G的空间(虚拟内存的大小,有面试官问过),从这个角度来看堆内存大小可以很大。但对于栈来说,一般都是有一定的空间大小的
3)碎片问题:堆频繁new/delete会造成内存空间的不连续,造成大量的碎片,使程序效率降低(重点是如何解决?如内存池、伙伴系统等)。对栈来说不会存在这个问题,因为栈是先进后出,不可能有一个内存块从栈中间弹出。在该块弹出之前,在它上面的(后进的栈内容)已经被弹出。
4)生长方向:堆生长(扩展)方向是向上的,也就是向着内存地址增加的方向;栈生长(扩展)方向是向下的,是向着内存地址减小的方向增长, 可以看第一张图。
5)分配方式:堆都是动态分配的,没有静态分配的堆。而栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,如局部变量分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,它的动态分配是由编译器进行释放,无需我们手工实现。
6)效率:栈是机器系统提供的数据结构,计算机会在底层对栈提供支持(有专门的寄存器存放栈的地址,压栈出栈都有专门的机器指令执行),这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的(可以了解侯捷老师的内存管理的视频,关于malloc/realloc/free函数等)。例如分配一块内存,堆会按照一定的算法,在堆内存中搜索可用的足够大小的空间,如果没有(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的内存空间,这样就有机会分到足够大小的内存,然后进行返回。总之,堆的效率比栈要低得多。

函数栈

函数栈又称为栈区
与堆区相对在内存中从高地址往低地址分配

栈帧是指函数(运行中且未完成)占用的一块独立的连续内存区域

应用中新创建的每个线程都有专用的栈空间,栈可以在线程期间自由使用。而线程中有千千万万的函数调用,这些函数共享进程的这个栈空间。每个函数所使用的栈空间是一个栈帧,所有的栈帧就组成了这个线程完整的栈

函数调用是发生在栈上的

  • 每个函数的相关信息(例如局部变量、调用记录等)都存储在一个栈帧中
  • 每执行一次函数调用就会生成一个与其相关的栈帧
  • 然后将其栈帧压入函数栈
  • 当函数执行结束则将此函数对应的栈帧出栈并释放掉

上经典
在这里插入图片描述
ARM压栈的顺序依次为当前函数指针PC、返回指针LR、栈指针SP、栈基址FP、传入参数个数及指针、本地变量和临时变量。如果函数准备调用另一个函数,跳转之前临时变量区先要保存另一个函数的参数。

其中
main stack frame为调用函数的栈帧
func1 stack frame为当前函数(被调用者)的栈帧
栈底在高地址,栈向下增长
FP就是栈基址,它指向函数的栈帧起始地址
SP则是函数的栈指针,它指向栈顶的位置

ARM也可以用栈基址和栈指针明确标示栈帧的位置,栈指针SP一直移动,ARM的特点是,两个栈空间内的地址(SP+FP)前面,必然有两个代码地址(PC+LR)明确标示着调用函数位置内的某个地址

ok其实还是有不好理解的地方的
R9为什么是the 5th parameter for func1:2 func1

当函数准备调用另一个函数时,在跳转之前,需要先保存另一个函数的参数。如果参数能够通过寄存器(如 R0-R3)传递,就直接使用寄存器;如果参数超过 4 个,多出来的参数则使用栈来传递,并将它们放置在当前函数栈帧的临时变量区。

所以在main函数栈帧的R9存放的是func1的第五个参数就没问题啦

注:ARM是满降栈

满栈:当堆栈指针总是指向最后压入堆栈的数据
空栈:当堆栈指针总是指向下一个将要放入数据的空位置

升栈:随着数据的入栈,SP指针从低地址->高地址移动
降栈:随着数据的入栈,SP指针从高地址->低地址移动

堆栈溢出

一般情况下应用程序是不需要考虑堆和栈的大小的,但是事实上堆和栈都不是无上限的,过多的递归会导致栈溢出,过多的alloc变量会导致堆溢出。
所以预防堆栈溢出的方法:
(1)避免层次过深的递归调用
(2)不要使用过多的局部变量,控制局部变量的大小
(3)避免分配占用空间太大的对象,并及时释放
(4)适当的情景下调用系统API修改线程的堆栈大小

栈的作用

(1)保存局部变量
(2)参数传递
(3)保存寄存器的值

参考博客

iOS-底层原理 24:内存五大区
ARM——栈

相关文章:

[iOS]内存分区

[iOS]内存分区 文章目录 [iOS]内存分区五大分区栈区堆区全局区常量区代码区验证内存使用注意事项总结 函数栈堆栈溢出栈的作用 参考博客 在iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域 还记得OC是C的超类 所以C的内存分区也是一样的 iOS系统中&a…...

sklearn基础教程:掌握机器学习入门的钥匙

sklearn基础教程:掌握机器学习入门的钥匙 在数据科学和机器学习的广阔领域中,scikit-learn(简称sklearn)无疑是最受欢迎且功能强大的库之一。它提供了简单而高效的数据挖掘和数据分析工具,让研究人员、数据科学家以及…...

【unity实战】使用unity制作一个红点系统

前言 注意,本文是本人的学习笔记记录,这里先记录基本的代码,后面用到了再回来进行实现和整理 素材 https://assetstore.unity.com/packages/2d/gui/icons/2d-simple-ui-pack-218050 框架: RedPointSystem.cs using System.…...

开发指南046-机构树控件

为了简化编程&#xff0c;平台封装了很多前端组件。机构树就是常用的组件之一。 基本用法&#xff1a; import QlmOrgTree from /qlmcomponents/tree/QlmOrgTree <QlmOrgTree></QlmOrgTree> 功能&#xff1a; 根据权限和控制参数显示机构树。机构树数据来源于核…...

SpringBatch文件读写ItemWriter,ItemReader使用详解

SpringBatch文件读写ItemWriter&#xff0c;ItemReader使用详解 1. ItemReaders 和 ItemWriters1.1. ItemReader1.2. ItemWriter1.3. ItemProcessor 2.FlatFileItemReader 和 FlatFileItemWriter2.1.平面文件2.1.1. FieldSet 2.2. FlatFileItemReader2.3. FlatFileItemWriter 3…...

如何评估AI模型:评估指标的分类、方法及案例解析

如何评估AI模型&#xff1a;评估指标的分类、方法及案例解析 引言第一部分&#xff1a;评估指标的分类第二部分&#xff1a;评估指标的数学基础第三部分&#xff1a;评估指标的选择与应用第四部分&#xff1a;评估指标的局限性第五部分&#xff1a;案例研究第六部分&#xff1a…...

程序员学CFA——经济学(七)

经济学&#xff08;七&#xff09; 汇率外汇市场外汇市场的功能外汇市场的参与者卖方买方 汇率的计算汇率报价基础货币与计价货币直接报价与间接报价外汇报价习惯 名义汇率和实际汇率货币的升值与贬值交叉汇率计算即期汇率与远期汇率即期汇率与远期汇率的概念远期升水/贴水远期…...

imx335帧率改到10fps的方法

验证: imx335.c驱动默认的帧率是30fps,要将 IMX335 的帧率更改为 10fps,需要调整与帧率相关的参数。FPS(frames per second,每秒帧数)通常由 sensor 的曝光时间(exposure time)和垂直总时间(VTS,Vertical Total Size)共同决定。VTS 定义了 sensor 完成一帧图像采集…...

Large Language Model系列之二:Transformers和预训练语言模型

Large Language Model系列之二&#xff1a;Transformers和预训练语言模型 1 Transformer模型 Transformer模型是一种基于自注意力机制的深度学习模型&#xff0c;它最初由Vaswani等人在2017年的论文《Attention Is All You Need》中提出&#xff0c;主要用于机器翻译任务。随…...

java后端项目启动失败,解决端口被占用问题

报错信息&#xff1a; Web server failed to start . Port 8020 was already in use. 1、查看端口号 netstat -ano | findstr 端口号 2、终止进程 taskkill /F /PID 进程ID 举例&#xff1a;关闭8020端口...

PostgreSQL安装/卸载(CentOS、Windows)

说明&#xff1a;PostgreSQL与MySQL一样&#xff0c;是一款开源免费的数据库技术&#xff0c;官方口号&#xff1a;The World’s Most Advanced Open Source Relational Database.&#xff08;世界上最先进的开源关系数据库&#xff09;&#xff0c;本文介绍如何在Windows、Cen…...

OutOfMemoryError异常OOM排查

目录 参考工具MAT(Memory Analyzer)一、产生原因二、测试堆溢出 java.lang.OutOfMemoryError: Java heap space测试代码运行手动导出dump文件mat排查打开dump文件查看Leak Suspects(泄露疑点)参考 【JVM】八、OOM异常的模拟 MAT工具分析Dump文件(大对象定位) 用arthas排…...

【Python】Arcpy将excel点生成shp文件

根据excel点经纬度数据&#xff0c;生成shp&#xff0c;参考博主的代码&#xff0c;进行了修改&#xff0c;在属性表中保留excel中的数据。 参考资料&#xff1a;http://t.csdnimg.cn/OleyT 注意修改以下两句中的数字。 latitude float(row[1]) longitude float(row[2])imp…...

torch之从.datasets.CIFAR10解压出训练与测试图片 (附带网盘链接)

前言 从官网上下载的是长这个样子的 想看图片&#xff0c;咋办咧&#xff0c;看下面代码 import torch import torchvision import numpy as np import os import cv2 batch_size 50transform_predict torchvision.transforms.Compose([torchvision.transforms.ToTensor(),…...

什么ISP?什么是IAP?

做单片机开发的工程师经常会听到两个词&#xff1a;ISP和IAP&#xff0c;但新手往往对这两个概念不是很清楚&#xff0c;今天就来和大家聊聊什么是ISP&#xff0c;什么是IAP&#xff1f; 一、ISP ISP的全称是&#xff1a;In System Programming&#xff0c;即在系统编程&…...

外卖霸王餐系统怎么快速盈利赚钱?

微客云外卖霸王餐系统&#xff0c;作为近年来外卖行业中的一股新兴力量&#xff0c;以其独特的商业模式和营销策略&#xff0c;迅速吸引了大量消费者的目光。该系统通过提供显著的折扣和返利&#xff0c;让顾客能够以极低的价格甚至免费享受到美味的外卖&#xff0c;同时&#…...

Linux环境下安装Nodejs

Linux环境下安装Nodejs 下载地址&#xff1a;https://nodejs.org/zh-cn/download/package-manager 一、使用压缩包自定义安装 上述链接下载好对应版本的软件包后&#xff0c;我存放到 /evn/nodejs 目录下&#xff08;根据自己实际情况设置&#xff09; 设置软链接 sudo ln…...

【Rust】字符串String类型学习

什么是String Rust的核心语言中只有一个String类型&#xff0c;那就是String slice,str通常被当作是&str的借用。String类型是通过标准库提供的&#xff0c;而不是直接编码到核心语言中&#xff0c;它是一个可增长的、可变的、utf-8编码的类型。str和String都是utf-8编码的…...

先验概率 后验概率 最大似然估计 自编码器AE

先验概率 先验概率&#xff1a;由因求果中的因 作用&#xff1a;后验概率是比较难以计算的&#xff0c;我们通常使用贝叶斯公式由先验概率计算后验概率。 贝叶斯公式&#xff1a;P(B|A)P(A|B)P(B)/P(A)&#xff0c;其中P(B|A)为后验概率&#xff0c;P(A|B)为先验概率。 后验…...

qt 鼠标接近某线时,形状变化举例

1.qt 鼠标接近某线时&#xff0c;形状变化举例 在Qt中&#xff0c;要实现鼠标接近某条线时形状发生变化的效果&#xff0c;你需要利用QWidget的enterEvent和leaveEvent&#xff0c;或者更通用的mouseMoveEvent来检测鼠标的位置&#xff0c;并相应地改变鼠标的光标形状。 以下…...

Linux链表操作全解析

Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表&#xff1f;1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...

智慧医疗能源事业线深度画像分析(上)

引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

docker详细操作--未完待续

docker介绍 docker官网: Docker&#xff1a;加速容器应用程序开发 harbor官网&#xff1a;Harbor - Harbor 中文 使用docker加速器: Docker镜像极速下载服务 - 毫秒镜像 是什么 Docker 是一种开源的容器化平台&#xff0c;用于将应用程序及其依赖项&#xff08;如库、运行时环…...

【JavaSE】绘图与事件入门学习笔记

-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角&#xff0c;以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向&#xff0c;距离坐标原点x个像素;第二个是y坐标&#xff0c;表示当前位置为垂直方向&#xff0c;距离坐标原点y个像素。 坐标体系-像素 …...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

React---day11

14.4 react-redux第三方库 提供connect、thunk之类的函数 以获取一个banner数据为例子 store&#xff1a; 我们在使用异步的时候理应是要使用中间件的&#xff0c;但是configureStore 已经自动集成了 redux-thunk&#xff0c;注意action里面要返回函数 import { configureS…...

比较数据迁移后MySQL数据库和OceanBase数据仓库中的表

设计一个MySQL数据库和OceanBase数据仓库的表数据比较的详细程序流程,两张表是相同的结构,都有整型主键id字段,需要每次从数据库分批取得2000条数据,用于比较,比较操作的同时可以再取2000条数据,等上一次比较完成之后,开始比较,直到比较完所有的数据。比较操作需要比较…...

论文阅读:LLM4Drive: A Survey of Large Language Models for Autonomous Driving

地址&#xff1a;LLM4Drive: A Survey of Large Language Models for Autonomous Driving 摘要翻译 自动驾驶技术作为推动交通和城市出行变革的催化剂&#xff0c;正从基于规则的系统向数据驱动策略转变。传统的模块化系统受限于级联模块间的累积误差和缺乏灵活性的预设规则。…...