内存学习笔记--堆、栈等

来源:互联网 发布:mac能做什么 编辑:程序博客网 时间:2024/06/06 23:16

一、数据存放形式:

一般来说,程序就是与数据打交道,在执行某一程序功能的时侯,将该功能所需要的数据加载到内存中,然后在执行完毕的时候释放掉该内存。

1、数据在内存中的存放形式共分为一下几种形式:

(1)、代码区:程序的代码(函数)放入代码区,函数指针就指向代码区,为只读区。
(2)、全局区:用来存放全局变量和static静态变量,在main执行之前分配全局区,可读可写。
(3)、BSS段:存放未初始化的全局变量。main函数执行之前清空BSS段(全局变量和static静态变量未初始化打印输出为0,而局部变量未初始化打印为随机值。

eg:#include<stdio.h>int i;//未初始化的全局变量,BSS段int j = 1;//初始化的全局变量,全局区int main(void){    static int k;//static静态变量,全局区    int l;//未初始化的局部变量,栈区    return 0;}

(4)、栈区:非static的局部变量,包括函数的参数。内存是自动分配自动回收的。
(5)、堆区:也叫自由区,malloc()、free()操作堆区,程序员完全掌控堆区内存的分配和回收,容易产生内存的泄露。
(6)、常量区:常量和字符串的字面值(”“)。
(7)、寄存器区:用来保存栈顶指针和指令指针。

2、虚拟内存地址:

每个进程都先天设定了4G的虚拟内存地址(不是真实的地址,只是一个编号)。虚拟内存开始时不对应任何内存,直接使用会引发段错误,不进入内核就接触不到物理内存地址,只会接触到虚拟内存地址。虚拟内存地址必须映射物理内存(或者硬盘上的文件)以后才能存储数据(数据存储在物理内存上,打印地址为虚拟内存地址)。而内存分配其实就是虚拟内存地址映射物理内存的过程,内存回收则是接触映射关系的过程。

二、栈区、堆区、全局区的特点:

1、栈区:

函数参数和局部变量存放在栈中,当函数运行结束并且返回时,所有的局部变量和参数就被系统自动清除掉了,为的是释放掉他们所占用的内存空间。

2、全局区:

全局变量可以解决这个需要不断重新为新的函数分配变量内存的问题,但是全局变量永远不会被释放,而且由于全局变量被所有类成员和函数共享,所以它们很容易被修改,不太安全。而使用堆可以解决这两个问题。

3、堆区:

堆是采用匿名的方式来存储(保存)数据的,只能通过指针才能访问到这些匿名的数据,所以堆的安全性是最好的,而且堆的空间是可以程序员自行分配和释放的,所以堆的自由度也是最高的。

三、堆与栈的区别:

1、内存申请方式的不同:

栈:

由系统自动分配(如:int i;由系统自动为i在内存中开辟一块4个字节的内存空)

堆:

需要程序员自己申请,因此也需要指明变量大小(如:动态内存分配int * p = (int *)malloc(sizeof(int));由程序员自行申请)

2、系统的响应不同:

栈:

只要系统剩余空间大于所申请空间,系统将会为程序提供内存,否则将提示overflow,即栈溢出

堆:

系统收到程序申请空间的要求后,会遍历整个操作系统用于记录内存空闲地址的链表,当找到一个空间大于所申请空间的堆节点后,就会将该节点从记录内存空闲地址的链表中删除。并将该节点的内存分配给程序,然后在这块内存区域的首地址处记录分配大小,这样我们在使用delete来释放内存的时候,delete才能够正确地识别并删除该内存区域的所有变量。另外,我们申请的空间与堆节点的内存空间不一定相等,这时系统就会自动将堆节点上多出的那一部分内存空间回收到空闲链表中。

3、空间大小的不同:

栈:

在Windows下,栈是一块连续的内存区域,它的大小是2M,也有说是1M,总之该数值是一个编译时就确定的常数。是由系统预先根据栈顶的地址和栈的最大容量定义好的。加入申请的空间超过栈的空间,那么就会提示overflow。因此别指望栈能存储较大的数据。

堆:

堆是不连续的内存区域,各块内存区域由链表将其串联起来,这些串联起来的内存空间叫做堆,它的上限是由系统中的虚拟内存来定的,因此获得的空间比较大,而且获得空间的方式也比较灵活。

4、执行效率不同:

栈:

栈由系统自动分配,因此速度较快。但是程序员不能对其进行操作。

堆:

堆是由程序员分配的内存,一般速度比较慢,而且容易产生内存碎片,但用起来比较方便。

5、执行函数时的不同:

栈:

(栈底是高内存地址,栈顶是低内存地址)
在函数调用时,第一个进栈的是被调函数下一行代码的内存地址。其次是函数的参数(参数多于一个时,最右边的先进栈如get(a,b),b先进栈,a后进栈),最后是局部变量。栈遵循先进后出原则,由于局部变量最后进栈,那么出栈(内存释放)时,首先是释放局部变量所占内存,其次是参数。当所有都已出栈,指针自然指到第一个进栈的那行代码的内存地址,程序根据该地址跳到被调函数的下一行继续执行。

堆:

堆是一大堆不连续的空间,堆的机制比较复杂,容易产生碎片,效率也低的多,但是堆可以存储相当大的数据,并且可以有程序员来安排,当我们需要创建一个对象,可以被多个函数访问但又不想其成为全局的对象时,堆无疑是最好的选择。由于堆栈各有优缺点,我们通常结合来使用,比如讲大数据存放在堆中,而将指向该数据的指针存放在栈中。

1 0
原创粉丝点击