在iOS中,大家平常经常说堆区,栈区,其实这些都是存在虚拟内存
虚拟内存可以主要分为五个大区(堆区、栈区、全局区、常量区、代码区)。
一、堆区(heap)
■ 是由程序员分配和释放,用于存放运行中被动态分配的内存段。大小不定,可增加和缩减
■ 堆向高地址扩展的数据结构,是不连续的内存区域。程序员负责在何时释放内存(如用free或delete
),在iOS的ARC程序中,系统自动管
■ 理计数器,计数器为0的时候,在当次的runloop
结束后,释放掉内存。堆中的所有东西都是匿名的,这样不能按名字访问,而只能通过指针访问。
■ 对于堆来讲,频繁的new/delete
势必会造成内存空间的不连续性,从而造成大量的碎片 ,使程序效率降低。
存储
堆区是由程序员动态分配和释放的,如果程序员不释放,程序结束后,可能由操作系统回收,主要用于存放:
■ OC
中使用alloc
或者 使用new
开辟空间创建对象
■ C语言中使用malloc、calloc、realloc
分配的空间,需要free
释放
优缺点
■ 优点:灵活方便,数据适应面广泛
■ 缺点:需手动管理,速度慢、容易产生内存碎片
■ 当需要访问堆中内存时,一般需要先通过对象读取到栈区的指针地址,然后通过指针地址访问堆区
二,栈区(stack)
■ 栈是由编译器分配和释放,用于存放程序临时创建的变量、函数的参数、局部变量等。
■ 是一块连续的内存区域,遵循先进后出的原则,向低地址的数据结构
■ 在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值 也会被存放回栈中。
■ 由于栈的后进先出特点,所以 栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
存储
栈区是由编译器自动分配并释放的,主要用来存储:
■局部变量
■函数的参数,例如函数的隐藏参数(id self,SEL _cmd)
优缺点
■优点:因为栈是由编译器自动分配并释放的,不会产生内存碎片,所以快速高效
■缺点:栈的内存大小有限制,数据不灵活
■iOS主线程栈大小是1MB
■其他线程是512KB
■MAC只有8M
三,全局区(静态)( bss segment )
■ 全局区是编译时分配的内存空间,在程序运行过程中,此内存中的数据一直存在,程序结束后由系统释放。static修饰的变量始终保存到常量区
■ 用来存放可执行文件中已经初始化的全局变量,也就是用来存放静态分配的变量和全局变量(.data)
■ 而bss段通常是指用来存放程序中未初始化的全局变量和静态变量的一块内存区域。
■ BSS段在程序执行之前会清0,所以未初始化的全局变量(静态变量)已经是0了。所以这种情况还是存放在BSS段,一旦初始化就会从BSS段中回收掉,转存到data段(数据段)中。
全局区是编译时分配
的内存空间,在iOS中一般以0x1
开头,在程序运行过程中,此内存中的数据一直存在,程序结束后由系统释放,主要存放:
■ 未初始化的全局变量和静态变量,即BSS
区(.bss)
■ 已初始化的全局变量和静态变量,即数据区(.data)
其中,全局变量
是指变量值可以在运行时被动态修改
,而静态变量
是static
修饰的变量,包含静态局部变量
和静态全局变量
四,常量区(data segment)
■ 是编译时分配的内存空间,在程序结束后由系统释放。存放的是常量,是一块特殊的区域
■ 通常是指用来存放程序中已经初始化的全局变量和静态变量的一块内存区域。数据段属于静态内存分配,可以分为只读数据段和读写数据段。字符串常量等,是放在只读数据段中,结束程序时才会被收回。
常量区是编译时分配的内存空间
,在程序结束后由系统释放,主要存放:
■ 已经使用了的,且没有指向的字符串常量
■ 字符串常量因为可能在程序中被多次使用,所以在程序运行之前就会提前分配内存
五,代码区(code segment/text segment)
■ 用来存放函数的二进制代码,它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,只允许读操作,不允许写操作
代码区是编译时分配
主要用于存放程序运行时的代码
,代码会被编译成二进制
存进内存
的