一、应用程序内存空间默认的区域

现在的应用程序都运行在一个内存空间里,以4g内存为例,大部分的操作系统都将4g内存空间的一部分挪给内核调用,应用程序无法直接访问这一段内存,这一部分内核地址成为内核空间,windows默认会将2g高地址空间分配给内核,而linux默认将高地址的1g空间分配给内核,用户使用剩下的2g、3g空间成为用户空间,用户空间一般有如下默认区域:

1.栈:栈用于维护函数调用的上下文,离开了栈函数调用就没办法实现

2.堆:堆是用来容纳应用程序动态分配的内存区域,当程序使用malloc或new分配内存时,得到的内存来自堆里。

3.可执行文件映像:这里存储着可执行文件在内存里的映像,有装载器在装载时将可执行文件的内存读取或映射到这里

4.保留区:保留区并不是一个单一的内存区域,而是对内存中受保护而禁止访问的内存区域的总称,例如大多数的操作系统里极小的地址区域都是不可访问的,如NULL。

二、栈与调用惯例

1.什么是栈

在经典的计算机科学中,将栈定义为一个容器,用户可以将数据压入栈中(入栈push),也可以将已压入栈中的数据弹出(出栈 pop),但栈这个容器必须遵守一个规则:先入栈的数据后出栈,在经典的操作系统里栈总是向下增长的压栈的操作使栈顶的地址减小,弹出的操作使栈顶的地址增大。

2.栈的调用惯例

函数的调用方和被调用方对函数如何调用需要有统一的理解,需要有一个明确的约定,只要双方都遵守同样的约定,函数才能被正确的调用,这样的约定称为调用惯例。

应用内存配置 Android 应用内存空间_应用内存配置 Android


三、堆与内存管理

1.什么是堆

光有栈对于面向过程的程序设计还远远不够,因为栈上的数据在函数返回的时候就会被释放掉,所以无法将数据传递至函数的外部,而全局变量没有办法动态的产生,只能编译的时候定义有很多情况下缺乏表现力,这种情况下,堆是唯一的选择。

堆是一块巨大的内存空间,常常占据整个虚拟空间的绝大部分,在这片空间里,程序可以请求一块连续的内存,并自由的使用,这块内存在程序主动放弃前都会一直保持有效

2.堆得内存管理

程序向操作系统申请一块适当大小的堆空间,然后由程序自己管理这块空间,而具体来讲管理着堆空间分配的往往是程序的运行库

运行库相当于向操作系统批发了一块较大的堆空间,然后零售给程序用,当全部零售完或程序有大量的内存需求时,再根据实际需求向操作系统进货,当然运行库在向程序零售堆空间时,必须管理它批发来的堆空间,不能把同一块地址出售两次,导致地址的冲突,于是运行库需要一个算法来管理堆空间,这个算法就是堆的分配算法,每个线程的栈都是独立的,所以一个进程中有多少个线程,就应该有多少个对应的栈,对于windows来说每个线程默认的栈大小是1MB,在线程启动时,系统会为它在进程地址空间中分配相应的空间作为栈,线程栈的大小可以有CreateThread参数指定,每个进程在创建时都有一个默认的堆,这个堆在进程启动时创建,并且进程结束时一直存在,默认堆的大小1MB,默认堆的大小肯定不够,可以用malloc申请,运行库的malloc函数是对堆管理器heapmanager函数(heapcreate创建一个堆,heapalloc在一个堆里给用户程序分配内存,heapfree释放已经分配的内存,heapdestroy摧毁一个堆)的封装。

3.堆的分配算法

空闲链表
位图
对象池