UI学习

  • iOS-底层原理 24:内存五大区
        • 总览
      • 一、栈区(Stack)
        • 1.1 核心特性
        • 1.2 优缺点
        • 1.3函数栈与栈帧
        • 1.3 堆栈溢出风险
      • 二、堆区(Heap);
        • 2.1 核心特性
        • 2.2 与栈区对比
      • 三、全局 / 静态区(Global/Static)
        • 3.1 内存划分
        • 3.2 关键区别
      • 四、常量区(Constant)
      • 五、代码区(Code/Text)
      • 面试问题学习;
        • 问题 1:`static`关键字的作用
        • 问题 2:堆内存碎片如何产生?
        • 问题3:请简述iOS应用程序的五大内存分区及其主要用途。
        • 问题4:为什么栈内存的分配和释放速度比堆内存快?
        • 问题5:全局区和静态区的内存是如何管理的?它们之间有什么区别? 有问题
      • 总结:内存分区速查表


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

总览

iOS 中,内存主要分为五大区域:栈区、堆区、全局区 / 静态区、常量区和代码区。内存布局总览如下:

请添加图片描述

由低地址到高地址依次为 代码区→常量区→全局 / 静态区→堆区→栈区,内核区位于最高地址。

一、栈区(Stack)

1.1 核心特性
  • 存储方向:从高地址向低地址分配,内存连续。

  • 管理方式:系统自动分配 / 释放(函数结束后立即回收)。

  • 典型存储:局部变量、方法参数(如self_cmd)、函数返回地址。

  • 地址特征:iOS 中以0X70X16开头。

示例代码

- (void)testStack {  int a = 10;  NSLog(@"a == %p size == %lu", &a, sizeof(a));  NSLog(@"方法参数 self:%p", &self);  NSLog(@"方法参数 cmd:%p", &_cmd);  
}  

输出结果

请添加图片描述

地址从0x16fdff2a8(self)→0x16fdff2a0(cmd)→0x16fdff29c(a),由高到低递减,步长 8 字节,验证栈的「后进先出」特性。

1.2 优缺点
  • 优点:速度快(系统自动管理)、无内存碎片。

  • 缺点:空间受限(iOS 主线程栈大小 1MB,其他线程 512KB)。

1.3函数栈与栈帧

栈帧定义
函数运行时在栈区分配的独立连续内存区域,包含:

  • 局部变量:函数内定义的变量(如int z = x + y;)。
  • 调用记录:返回地址(LR)、当前函数指针(PC)、栈基址(FP)、栈指针(SP)等。
  • 参数传递:函数参数通过栈帧传递(如Add(a, b)中的ab)。

函数调用流程

  1. 压栈

    :调用函数时,系统创建新栈帧,将参数、局部变量、PC/LR 等压入栈区。

    • 例:main函数调用Add(a, b)时,先压入ab,再压入Add函数的栈帧。
  2. 执行:函数在栈帧内执行,操作局部变量(如计算z = x + y)。

  3. 出栈:函数执行完毕,栈帧出栈,释放内存,程序通过 LR 返回调用处(如从Add返回main)。

- (void)testStackFrame {  int a = 10;  int b = 20;  int sum = [self addWithA:a b:b];  NSLog(@"sum = %d", sum);  
}  - (int)addWithA:(int)a b:(int)b {  return a + b;  
}  

栈帧变化

  1. testStackFrame调用时,栈帧压入absum等局部变量。
  2. 调用addWithA:b:时,新栈帧压入参数ab,计算后通过 LR 返回结果。
  3. 函数结束后,两层栈帧依次出栈,释放内存。
1.3 堆栈溢出风险
  • 栈溢出:
    • 原因:递归深度过深(如无限递归)或局部变量过多,超过栈空间限制(如主线程 1MB)。
    • 后果:程序崩溃,抛出EXC_BAD_ACCESS异常。
  • 堆溢出:
    • 原因:频繁分配大内存(如循环创建未释放的对象),耗尽虚拟内存。
    • 后果:内存不足,系统终止进程。

二、堆区(Heap);

2.1 核心特性
  • 存储方向:从低地址向高地址分配,内存不连续(基于链表管理)。

  • 管理方式:手动分配 / 释放(alloc/free等),需避免内存泄漏。

  • 典型存储:OC 对象([NSObject new])、动态分配的数据(malloc)。

  • 地址特征:iOS 中以0x6开头。

示例代码

- (void)testHeap {  NSObject *object1 = [NSObject new];  NSObject *object2 = [NSObject new];  NSLog(@"object1 = %@", object1);  NSLog(@"object2 = %@", object2);  
}  

输出结果

请添加图片描述

地址0x6000029ac0700x6000029ac080不连续,验证堆的「非连续分配」特性。

2.2 与栈区对比
维度栈区堆区
分配方式 系统自动(LIFO) 手动分配(链表遍历)
内存连续性 连续 不连续
生命周期 函数作用域内 手动释放或程序结束
空间大小 受限(1MB/512KB) 受限于虚拟内存
碎片问题 易产生

三、全局 / 静态区(Global/Static)

3.1 内存划分
  • .bss 段:存储未初始化的全局变量和静态变量,程序启动时自动清零。

  • .data 段:存储已初始化的全局变量和静态变量

示例代码

int globalVar;          // 未初始化全局变量(.bss)  
static int staticVar;   // 未初始化静态变量(.bss)  
int initGlobal = 10;    // 已初始化全局变量(.data)  
static int initStatic = 11; // 已初始化静态变量(.data)  - (void)testStatic {  NSLog(@"globalVar = %p", &globalVar);  NSLog(@"staticVar = %p", &staticVar);  NSLog(@"initGlobal = %p", &initGlobal);  NSLog(@"initStatic = %p", &initStatic);  
}  

输出结果

请添加图片描述

分析

  • .bss段地址连续(0x1000081000x10008104,相差 4 字节)。

  • .data段地址连续(0x1000080f80x1000080fc,相差 4 字节)。

3.2 关键区别
类型作用域初始化时机
全局变量 全程序可见 程序启动时分配
静态全局变量 当前文件可见 程序启动时分配
静态局部变量 函数内可见 第一次调用时分配

四、常量区(Constant)

  • 存储内容:字符串常量(如@"Hello")、基本类型常量(如1233.14)。

  • 特性

    • 只读,程序运行时不可修改。
    • 编译时分配,程序结束后由系统释放。

五、代码区(Code/Text)

  • 存储内容:编译后的二进制指令(函数体、方法实现)。

  • 特性

    • 只读,防止程序运行中意外修改代码。

    • 共享性:相同程序的多个实例共享代码区(如多个 App 进程共享系统库代码)。

    • 安全意义:阻止恶意代码注入和篡改,防御缓冲区溢出攻击。

面试问题学习;

问题 1:static关键字的作用
  • 对于全局变量来说,static 改变了其作用域。普通全局变量是所有文件都可以用。静态全局变量是只有当前文件可以用。
  • 对于局部变量来说,static改变了其存储方式从而改变了生命周期。普通局部变量是动态存储,动态存储决定了其生命周期为变量使用期间。静态局部变量是静态存储,存储在全局静态区,生命周期为从程序开始到结束。
  • 因此 static 这个说明符在不同的地方所起的作用是不同的。
  • 总结:全局变量、静态全局变量、静态局部变量采用静态存储方式,局部变量采用动态存储方式。
问题 2:堆内存碎片如何产生?
  • 原因:频繁分配 / 释放不同大小的内存块,导致空闲内存碎片化(如分配 100 字节→释放→分配 20 字节→释放,留下 80 字节小块无法被大内存请求利用)。

  • iOS 优化方案

    • 使用 ARC 自动管理内存,减少手动操作。
      
    • 对象池技术(如`NSOperationQueue`复用线程)。
      
    • 避免高频小内存分配(如改用缓存机制)。
      
问题3:请简述iOS应用程序的五大内存分区及其主要用途。
  1. 栈(Stack)

    • 用途:用于存储局部变量、函数参数、返回地址等。栈内存是自动分配和释放的,主要用于函数调用和局部变量的管理。
    • 特点:内存分配方式为LIFO(后进先出),存取速度快,空间相对较小。
  2. 堆(Heap)

    • 用途:用于动态分配内存,存储需要在运行时分配和释放的对象和数据。堆内存由程序员手动管理,通过mallocfreenewdelete等函数进行分配和释放。
    • 特点:内存管理灵活,存储空间较大,但分配和释放速度相对较慢,容易产生内存碎片。
  3. 全局区/静态区(Global/Static)

    • 用途:存储全局变量和静态变量。全局变量在程序启动时分配,在程序结束时释放;静态变量在第一次使用时分配,程序结束时释放。
    • 特点:内存地址固定,生命周期贯穿程序运行的整个周期。
  4. 常量区(Constant)

    • 用途:存储常量数据,例如字符串常量、数值常量等。常量区的内容在程序运行时不可修改。
    • 特点:只读区域,数据在程序加载时初始化,生命周期贯穿程序运行的整个周期。
  5. 代码区(Code/Text)

    • 用途:存储程序的可执行代码,包括函数体和编译后的指令。代码区在程序运行时是只读的,以防止意外修改。
    • 特点:只读区域,存储的是编译后的机器指令,生命周期贯穿程序运行的整个周期。
问题4:为什么栈内存的分配和释放速度比堆内存快?
  1. 分配方式:栈内存采用LIFO(后进先出)的分配方式,每次函数调用时,函数的局部变量、参数和返回地址会依次入栈,函数返回时,这些数据会依次出栈。分配和释放只需要移动栈指针,操作简单且高效。
  2. 内存管理:栈内存由系统自动管理,函数调用结束时,系统会自动释放栈内存,无需程序员手动管理。堆内存则需要程序员手动管理,通过mallocfree等函数进行分配和释放,管理复杂且容易产生内存碎片。
  3. 空间连续:栈内存通常是连续的内存块,分配和释放时不需要进行复杂的内存碎片整理,而堆内存由于频繁的分配和释放,容易产生内存碎片,导致分配和释放速度变慢。
问题5:全局区和静态区的内存是如何管理的?它们之间有什么区别? 有问题
  • 全局区(Global)

    • 管理全局变量,即在程序的整个生命周期内都存在的变量。这些变量在程序启动时分配内存,在程序结束时释放内存。
    • 全局变量在定义时如果未显式初始化,系统会将其初始化为0。
  • 静态区(Static)

    • 管理静态变量,即在函数或类内部定义并带有static关键字的变量。这些变量在第一次使用时分配内存,在程序结束时释放内存。
    • 静态变量在第一次定义时如果未显式初始化,系统也会将其初始化为0。

区别

  • 生命周期:全局变量和静态变量的生命周期相似,都是在程序运行期间存在,但全局变量在程序启动时即被初始化,而静态变量在第一次使用时才被初始化。
  • 作用域:全局变量的作用域是整个程序,而静态变量的作用域仅限于其定义的函数或类内部。

总结:内存分区速查表

分区地址方向 读写权限 管理方式 典型存储
栈区 高→低 可读可写 系统自动 局部变量、函数参数
堆区 低→高 可读可写 手动分配 OC 对象、动态数据
全局 / 静态区 固定 可读可写 编译时分配 全局变量、静态变量
常量区 固定 只读 编译时分配 字符串、数值常量
代码区 固定 只读 编译时分配 可执行指令

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

每日一题【删除有序数组中的重复项 II】

删除有序数组中的重复项 II思路class Solution { public:int removeDuplicates(vector<int>& nums) {if(nums.size()<2){return nums.size();}int index 2;for (int i 2; i < nums.size();i ) {if(nums[i] ! nums[index-2]) {nums[index]nums[i];}}return ind…

兼容性问题记录

1、dialog设置高度MATCH_PARENT全屏后&#xff0c;三星机型和好像是一加&#xff0c;会带出顶部状态栏&#xff0c;设置隐藏状态栏属性无效。解决方法&#xff1a;高度不设置为MATCH_PARENT&#xff0c;通过windowmanager.getdefaultdisplay来获取并设置高度&#xff0c;再设置…

6.数组和字符串

在C语言中&#xff0c;数组和字符串是基础且重要的概念。它们用于存储和操作一系列相同类型的元素或字符序列。数组1. 数组定义与初始化数组是一系列相同类型的数据项的集合&#xff0c;这些数据项可以通过一个共同的名字来引用。数组中的每个元素都有一个索引&#xff08;也称…

odoo代码分析(一)

Odoo 是一套基于网络的开放式源代码商业应用套件,既可以作为独立应用运行,也可以作为集成的全功能 ERP 系统使用。Odoo 平台采用模块化架构,允许组织根据自身需求起步,并在需求增长时扩展功能。 什么是 Odoo? Odoo 提供了一个完整的商业应用生态系统,包括: 客户关系管…

从“人工眼”到‘智能眼’:EZ-Vision视觉系统如何重构生产线视觉检测精度?

制造业是我国实体经济的基础&#xff0c;是国内经济增长的重要引擎。制造业智能化建设是当下的必然趋势&#xff0c;然而目前依旧有很多中小型企业因为成本原因&#xff0c;无法加快智能化制造的步伐。在智能检测领域更是如此&#xff0c;很多企业依旧在采用人工检测&#xff0…

Etcd原理基础学习

etcd 是一个开源的分布式键值存储系统&#xff0c;专注于提供高可用性、强一致性的数据存储与访问&#xff0c;广泛应用于分布式系统的服务发现、配置管理和协调任务。以下是其核心特性和应用场景的详细介绍。接下来就看看Etcd如何实现服务注册&#xff0c;以及如何通过Raft算法…

【硬件-笔试面试题】硬件/电子工程师,笔试面试题-32,(知识点:模数转换器,信噪比,计算公式,)

目录 1、题目 2、解答 步骤一&#xff1a;明确理想 ADC 的信噪比公式 步骤二&#xff1a;推导公式的来源 步骤三&#xff1a;得出答案 3、相关知识点 一、信噪比&#xff08;SNR&#xff09;的定义 二、理想 ADC 的量化噪声 三、满量程正弦波信号的功率 四、信噪比公…

Redis过期数据的删除策略是什么?有哪些?

定时删除&#xff1a;- 每个设置了TTL的key中都会创建一个计时器&#xff0c;等到过期时间就会立即删除- 对内存友好&#xff0c;但是会占用大量的CPU资源去处理过期数据&#xff0c;从而影响缓存的吞吐量和响应时间惰性删除&#xff1a;- 设置了key的过期后&#xff0c;不会立…

linux dd命令详解

dd 是一个功能强大的 Unix/Linux 命令行工具&#xff0c;用于低级别的字节流操作&#xff0c;常用于创建、复制、转换和处理文件或设备数据。它在 macOS 和 Linux 系统上都可用&#xff0c;但在 macOS 上有一些细微差异。本文将详细讲解 dd 命令的用法&#xff0c;包括参数、常…

多线程同步技术是用于协调多个线程访问共享资源或执行顺序的机制,以避免数据竞争、死锁、线程不安全等问题

多线程同步技术是用于协调多个线程访问共享资源或执行顺序的机制,以避免数据竞争、死锁、线程不安全等问题。 在提供的代码中,存在多线程操作加热板的场景,涉及锁竞争和硬件资源访问,优化多线程同步可以显著提升程序性能和稳定性。 以下是多线程同步技术的详细解释、常见…

CRMEB标准版,从创建数据表到实现最基础增删改查的实现过程

很多使用了CRMEB单商户系统的童鞋在进行二开的时候&#xff0c;都会遇到新建了数据表之后不知道对数据表怎么进行操作。那么&#xff0c;这篇文章将带你完整的实现一遍&#xff0c;以后就不会怕啦。一、创建数据表就以最简单的为例&#xff0c;创建一个学生的信息表编号姓名性别…

J2EE模式---数据访问对象模式

数据访问对象模式基础概念数据访问对象模式&#xff08;Data Access Object Pattern&#xff0c;简称 DAO 模式&#xff09;是一种结构型设计模式&#xff0c;其核心思想是将数据访问逻辑与业务逻辑分离&#xff0c;通过一个抽象层&#xff08;DAO&#xff09;来处理数据的持久…

【OpenCV篇】OpenCV——02day.图像预处理(1)

目录 前言 一、图像色彩空间转换 1 RGB颜色空间 2 颜色加法 3 颜色加权加法 4 HSV颜色空间 5 RGB转Gray(灰度) 二、灰度实验 1 灰度图 2 最大值法 3 平均值法 4 加权均值法 5 两个极端的灰度值 三、图像二值化处理 二值图像 1 阈值法(THRESH_BINARY) 2 反阈值…

经典IDE之Turbo C

写的程序不多&#xff0c;换过的 IDE 不少&#xff0c;本文将列举曾经用过的不同 C 语言相关的 IDE 环境&#xff0c;既是纪念&#xff0c;也是回忆。值得注意的是 IDE 的出现是为了提高开发效率&#xff0c;有一个相对成熟的编译环境和程序。从编程的角度来看&#xff0c;过分…

Go 多模块仓库标签管理教程

为了方便自己开发&#xff0c;自己写了个小工具&#xff1a;DzhGO 代码生成工具 功能特点标题 初始化项目基础结构生成插件模块代码生成模型和实体代码生成服务接口和实现代码支持 admin 和 app 两种模块类型生成项目基础目录 具体介绍看仓库&#xff1a; https://github.co…

IDEA 类上方注释 签名

File -->settings–>Editor–>File and Code Templates–>class新建 Class 类上方添加内容&#xff1a;/*** author Jagger* since ${DATE} ${TIME}*/

卫星通信终端天线对星之:参考星对星

我们在前面的文章中介绍了3种卫星通信终端的对星模式&#xff0c;分别是&#xff1a; 卫星通信终端天线的5种对星模式之一&#xff1a;信标跟踪 卫星通信终端天线的5种对星模式之二&#xff1a;功率检测型载波跟踪 卫星通信终端天线的5种对星模式之二&#xff1a;DVB跟踪 今…

来自麻省理工和AI制药公司 Recursion 的结构与结合亲和力预测模型Boltz-2,解决小分子药物发现的关键问题

1. Boltz-2介绍 文章来源&#xff1a;http://jeremywohlwend.com/assets/boltz2.pdf 开源代码来源&#xff1a;https://github.com/jwohlwend/boltz 该AI模型由麻省理工学院计算机科学与人工智能实验室与上市AI制药公司Recursion一起开发&#xff0c;双方在Boltz-1的基础之上…

从零用java实现 小红书 springboot vue uniapp(14) 集成阿里云短信验证码

从零用java实现 小红书 springboot vue uniapp&#xff08;14&#xff09; 集成阿里云短信验证码 移动端演示 http://8.146.211.120:8081/#/ 管理端演示 http://8.146.211.120:8088/#/ 项目整体介绍及演示 前言 在现代应用中&#xff0c;手机号不仅是用户的唯一标识&#xff0…

`<< EOF` 与 `<< ‘EOF‘` 与 `<< “EOF“`有无引号的区别多回答笔记250722

<< EOF 与 << EOF 与 << "EOF"有无引号的区别多回答笔记250722 实测 自测代码: # 定义变量 hello"ni hao"# 无引号 tee << EOF # 无引号 ${hello} world \n $(date) # 无引号 EOF# 单引号 tee << EOF # 单…