iOS中,内存主要分为栈区、堆区、全局区、常量区、代码区五大区域
1. 栈区
定义
栈是系统数据结构,其对应的进程或者线程是唯一的
栈是向低地址扩展的数据结构
栈是一块连续的内存区域,遵循先进后出(FILO)原则
栈的地址空间在iOS中是以0X7开头
栈区一般在运行时分配
存储
栈区是由编译器自动分配并释放的,主要用来存储
局部变量
函数的参数,例如函数的隐藏参数(id self,SEL _cmd)
优缺点
优点:因为栈是由编译器自动分配并释放的,不会产生内存碎片,所以快速高效
缺点:栈的内存大小有限制,数据不灵活
iOS主线程栈大小是1MB
其他主线程是512KB
MAC只有8M
传入函数的参数值、函数体内声明的局部变量等,由编译器自动分配释放,通常在函数执行结束后就释放了。(注意:不包括static修饰的变量,static意味该变量存放在全局/静态区)其操作方式类似数据结构中的栈,先进后出。
栈内存分配运算内置于处理器的指令集,效率很高,但是分配的内存容量有限,比如iOS中栈区的大小是2M(看网上说,也有人说1M,我也不知道具体大小,但栈区的内存肯定不会太大)。
存放的局部变量、先进后出、一旦出了作用域就会被销毁;函数跳转地址,现场保护等;
程序猿不需要管理栈区变量的内存
栈区地址从高到低分配;
2.堆区
定义
堆是向高地址扩展的数据结构
堆是不连续的内存区域,类似于链表结构(便于增删,不便于查询),遵循先进先出(FIFO)原则
堆的地址空间在iOS中是以0x6开头,其空间的分配总是动态的
堆区的分配一般是在运行时分配
存储
堆区是由程序员动态分配和释放的,如果程序员不释放,程序结束后,可能由操作系统回收,主要用于存放
OC中使用alloc或者 使用new开辟空间创建对象
C语言中使用malloc、calloc、realloc分配的空间,需要free释放
优缺点
优点:灵活方便,数据适应面广泛
缺点:需手动管理,速度慢、容易产生内存碎片
当需要访问堆中内存时,一般需要先通过对象读取到栈区的指针地址,然后通过指针地址访问堆区
堆区的内存是由代码分配和释放,用于存放进程运行中被动态分配的内存段,堆区的大小并不固定,可动态扩张或缩减。
变量通过new、alloc、malloc、realloc分配的内存块就存放在堆区。
堆区的内存都是动态分配的。
当进程调用alloc等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张)。
当利用realse释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
如果应用程序没有释放掉,操作系统会自动回收,分配方式类似于链表。
因为现在iOS基本都使用ARC来管理对象,所以也不需要手动释放。
一般速度比较慢,而且容易产生内存碎片,不过用起来最方便。
3. 全局/静态区域 即.bss
全局区是编译时分配的内存空间,在iOS中一般以0x1开头,在程序运行过程中,此内存中的数据一直存在,程序结束后由系统释放,主要存放
未初始化的全局变量
未初始化的静态变量
由static修饰的变量会成为静态变量,该变量的内存由全局/静态区在编译阶段完成分配,且仅分配一次。
static可以修饰局部变量也可以修饰全局变量。
4. 常量区
常量区是编译时分配的内存空间,在iOS中一般以0x1开头,在程序结束后由系统释放,主要存放
已初始化的全局变量
已初始化的静态变量(即Static)
5. 代码区
代码区是编译时分配主要用于存放程序运行时的代码,代码会被编译成二进制存进内存的
代码区需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。
通常代码段是可共享的,这使得需要频繁被执行的程序只需要在内存中拥有一份拷贝即可。代码段也通常是只读的,这样可以防止其他程序意外地修改其指令。另外,代码段还规划了局部数据所申请的内存空间信息。 代码段(code segment/text segment)通常是指用来存放程序执行代码的一块内存区域。这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许修改程序。在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
未完待续~