ios 堆、栈,全局区 入门理解

2,964 阅读4分钟

存储区

  • 栈:编译器自动分配和释放,存放函数参数值,局部变量,(swift结构体,栈block)等。

  • 堆:程序员画管理释放。分配方式倒是类似于链表。就是通过new、malloc、realloc分配的内存块,编译器不会负责它们的释放工作,需要用程序区释放。分配方式类似于数据结构中的链表。在iOS开发中所说的“泄漏”说的就是堆区的内存。

  • 全局区:全局变量和静态变量 。初始化过的全局变量和静态变量在同一块区域,未初始化的全局变量和静态变量存放在一块相邻的区域内。此区域由系统在程序结束后释放。

  • 文字常量区:常量字符串,程序结束后由系统释放

  • 程序代码区:存放函数二进制代码。在程序结束后由系统释放。

栈与堆的比较:

  1. 分配方式不同
  • 栈:编译器自动分配和释放,例如函数中的局部变量,随着函数的结束释放
  • 堆:程序员自己申请。
  1. 空间大小。 堆的空间很大几个G。而栈就1M或者其他。比如iOS中栈区的大小是2M。
  2. 分配效率
  • 栈:是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执 行,这就决定了栈的效率比较高。
  • 堆:为了分配一块内存,库函数会按照一定的算法在堆内存中搜索可用的足够大小的空间,如果没有足够大小的空间(可能是由于内存碎片太多),就有可能调用系统功能去增加程序数据段的 内存空间,这样就有机会分到足够大小的内存,然后进行返回。显然,堆的效率比栈要低得多。
  1. 碎片问题
  • 栈:不存在碎片问题。只要剩余内存够就可以存。否则就会异常,先进后出的队列
  • 堆:有一个记录空闲地址的链表。存东西的时候会遍历这个列表,找到一个空间大于申请空间的堆节点,然后删除,并记录本次分配大小。
  1. 对于栈来说他的内存是向下的,越存越小。 但是堆回因为不断的申请内存慢慢变大

总结:可以看得出,栈的好处很明显,分配效率高,没有碎片。所以在函数调用的参数,局部变量都是栈来完成的。但是相对堆相比需要分配大量顽固的的内存还是用堆比较好,堆的内存空间相对灵活。

关键字

  1. const 总结。 如果星号在左边。值不能改 ,如果星号在右边 地址不能改。

  2. static

  • static限制了变量的作用域为当前文件, 其他文件可以定义一个相同的static变量, 如果没有static修饰, 在其他文件中定义了相同名称的全局变量, 会报错
  • static关键字用来修饰变量的作用域会变成当前文件,生命也会变长
  • static修饰的变量只会分配一份内存.它只被初始化一次
  • static修饰局部变量, 在上一次修改的基础上进行修改 但是生命周期也比较长。
  1. extern 就是一种申明。1、可在.m 中申明有一个全局变量可以访问,也可以在.h 中申明这个变量外界可以访问。

常见变量

  • 全局变量 (写在类的最上面的) — 全局静态储蓄取。 可以搭配 extern 使用

全局变量具有全局作用域。全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用extern 关键字再次声明这个全局变量。

  • 局部变量 (函数里面的) -- 保存在每次函数执行的栈中,随着函数的结束释放。

局部变量也只有局部作用域,它是自动对象(auto),它在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。

  • 静态局部变量 (staic修饰的) — 全局静态储蓄取,它只被初始化一次

静态局部变量具有局部作用域,它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。

  • 静态全局变量 (staic修饰的) — 全局静态储蓄取,它只被初始化一次

就像上面说的全局变量被static修饰,那么就作用当前文件,切其他文件可以于其重名。