【iOS】内存分区


前言

最近看源码啥的看的头大,最近学一些容易理解其他知识

内存布局

iOS的内存分区分为五大分区:
栈区堆区全局区常量区代码区
在这里插入图片描述
在这里插入图片描述

栈区

创建临时变量时由编译器自动分配,在不需要的时候自动消除变量的存储区
主要用于存储函数的局部变量、函数参数和返回地址,遵循先进后出原则

优点:

  • 栈是系统数据结构,每个线程独有一个栈,每个进程也独有一个栈,栈包含了线程执行所需要的所有局部变量,函数参数,返回地址等
  • 快速高效,缺点是有限制,数据不灵活
  • 同时栈的空间还分为静态分配与动态分配,静态分配是由编译器完成的,动态分配是运行时决定的
void function() {
    int localVar = 10;  // 局部变量,静态分配在栈上
    char buffer[100];  // 在编译时分配固定大小的数组
}
void dynamicAllocation(size_t size) {
    int runtimeArray[size];  // 变长数组,根据运行时的size决定大小
}
  • 同时还存储了函数的隐藏参数(id self,SEL _cmd)

传入函数的参数值、函数体内声明的局部变量等,由编译器自动分配释放,通常在函数执行结束后就释放了。(注意:不包括static修饰的变量,static意味该变量存放在全局/静态区)

堆区

特点:

  • 堆是一块不连续的区域,类似于链表结构,便于增删不便于查询,遵循先进先出FIFO)原则
  • 堆区的内存一般是运行时分配的

存储内容

  • 堆区的内存是由程序员手动分配的,在ARC中经常会自动回收
  • 在OC中经常使用alloc或是new开辟堆空间和创建对象,在C语言中使用的malloc等分配的空间需要手动释放

我们来看一个分配堆内存的例子

NSObject *obj = [NSObject new];

对于这段代码来说总共进行了四步

  1. 在堆内存中申请一块大小合适的空间
  2. 在这块内存空间里创建我们的对象
  3. 初始化对象的属性,为对象的属性赋默认值,==基本数据类型赋值0->C指针类型为NULL->OC指针类型为nil
  4. 返回这个对象在堆空间的地址,将这个地址赋给obj,以后我们访问obj变量时实际访问的就是堆空间中的的NSObject对象,但是obj变量因为本质上是一个指针变量,他是存储在栈空间的,这个我们后面验证

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

缺点
需手动管理,速度慢、容易产生内存碎片

全局区(静态区)

全局区分为两个区域,bss段与data段,用于存储全局变量与静态变亮

  • BSS
    用于存放程序中未初始化的或者初始值为0的全局变量的一块内存区域
  • data
    存放明确赋初值的全局和静态变量

常量区

特点:用于存储程序中的常量数据,如字符串字面量
用途:这部分内存通常是只读的,确保常量值不会被程序意外修改。

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *string1 = @"Hello, World!";
        NSString *string2 = @"Hello, World!";
        
        if (string1 == string2) {
            NSLog(@"string1 and string2 are the same instance");
        } else {
            NSLog(@"string1 and string2 are different instances");
        }
        
        // 创建不可变的 NSNumber 常量
        NSNumber *number = @42;
        NSLog(@"Number: %@", number);
    }
    return 0;
}

在这个例子中:
1. @"Hello, World!" 是一个字符串字面量,它被存储在常量区。由于常量区中的字符串是唯一的,所以 string1 和 string2 实际上指向同一个内存地址。
2. @42 是一个 NSNumber常量,它也被存储在常量区。

代码区

程序代码区:用来存放函数的二进制代码
代码区需要防止运行时被非法修改,所以只允许读取不允许写入

总结

  • 栈区存储临时变量、函数参数以及函数地址,数据结构符合先进后出
  • 堆区存储运行时创建的对象,数据结构符合先进先出
  • 常量区存储字符串字面量,常量区的字符串是唯一的
  • 代码区存储存放函数的二进制代码,只允许读取操作
  • 全局静态区存储全局变量与静态变量,分为两个区域,一个为BSS区存储未初始化的变量,另一区域存储已经初始化的全局静态变量

相关推荐

  1. IO内存访问函数

    2024-05-25 22:00:48       65 阅读
  2. FFmepg--内存IO模式

    2024-05-25 22:00:48       44 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-25 22:00:48       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-25 22:00:48       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-25 22:00:48       82 阅读
  4. Python语言-面向对象

    2024-05-25 22:00:48       91 阅读

热门阅读

  1. 一些Spring Boot直接的解释

    2024-05-25 22:00:48       32 阅读
  2. 判断当前系统是linux、windows还是MacOS (python)

    2024-05-25 22:00:48       30 阅读
  3. C++基础:构建者设计模式

    2024-05-25 22:00:48       30 阅读
  4. 单元测试:保证重构不出错的有效手段

    2024-05-25 22:00:48       33 阅读
  5. 【LeetCode面试经典150题】101. 对称二叉树

    2024-05-25 22:00:48       36 阅读
  6. 物理服务器都有哪些作用?

    2024-05-25 22:00:48       34 阅读
  7. 服务器漏洞安全修复记录

    2024-05-25 22:00:48       30 阅读
  8. 什么是容器?

    2024-05-25 22:00:48       33 阅读
  9. Python镜像服务器

    2024-05-25 22:00:48       35 阅读
  10. 详解 Scala 的运算符

    2024-05-25 22:00:48       30 阅读
  11. vue项目移动端商场

    2024-05-25 22:00:48       33 阅读
  12. Scala基础语法

    2024-05-25 22:00:48       27 阅读
  13. Android make命令简述

    2024-05-25 22:00:48       32 阅读