栈(stack)
-
为编译器自动分配和释放,速度快,(如函数参数、函数返回地址,局部变量、临时变量等等)
-
栈的特性:后入先出LIFO
栈需要存储函数中的局部变量和参数,函数又是最后调用的最先销毁,栈的后进先出正好满足这一点。 -
栈由高地址向低地址扩展,栈内是连续分配内存的。
如果给一个数组或对象分配内存,栈会选择还没分配的最小的内存地址给数组,在这个内存块中,数组中的元素从低地址到高地址依次分配(不要和栈的从高到低弄混了)。所以数组中第一个元素的其实地址对应于已分配栈的最低地址。 -
栈只能获取栈顶的内存地址
所以如果栈是从高地址往低地址扩展的话,正好栈顶指向数组的起始地址,即数组的指针。而如果栈还采用从低地址到高地址扩展,那么不会指向数组的指针。
堆(heap)
- 自由分配,自己申请,自己释放(否则发生内存泄漏),速度较慢,更灵活
- 堆的特性:先入先出FIFO
- 堆的内存地址是不连续的,由低地址向高地址扩展,一般是链表结构。
内存地址空间(虚拟)
-
每个进程都会分配4G空间,都有同样的虚拟地址,但是由于映射的物理内存地址不同, 所以不会冲突。
-
需要用到的指令和数据会传入物理内存,暂时不用的会根据算法临时存放在硬盘的页交换区
-
之所以是4G,因位在32位架构下,一个指针的大小是4字节(4*8=32),2的32次方正好是4G寻址能力(每个地址单元是字节Byte)
-
32位windows下,一个进程空间4G,内核占2G,留给用户只有2G,一个线程默认栈是1M,所以一个进程最大开2048个线程。当然内存不会完全拿来做线程的栈,所以最大线程数实际值要小于2048,大概2000个。
-
32位Linux下,一个进程空间4G,内核占1G,用户留3G,一个线程默认8M,所以最多380个左右线程。(ps:ulimit -a
查看电脑的最大进程数,大概7000多个) -
虚拟内存一般分为以下4大块:
1,栈空间:特点是由系统管理,先进后出,里面放了局部变量、函数形参、自动变量。
2,堆空间:特点是由用户管理,先进后出,我们可以用malloc、ralloc、calloc来分配空间。
3,数据段:数据段里面又分三块,
第一块是bss,保存未初始化的全局变量;
第二块是rodata,保存了常量;
第三块 是.data(静态数据区)保存了初始化的全局变量还有static修饰的变量。
4,代码段:存放了源代码。