heap和stack的差别

heapstack的差别

  在进行c/c++编程时,需要程序员对内存的了解比较精准。经常需要操作的内存可分为以下几个类别。

  栈区(stack):由编译器自动分配和释放,存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈。

  堆区(heap):一般由程序员分配和释放,若程序员不释放,程序结束时可能由操作系统回收,存放new、malloc等变量。但是它与数据结构中的堆是两回事,分配方式倒是类似于链表。

  全局区(静态区)(static):全局变量和static变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和static变量在相邻的另一块区域。程序结束后由系统释放。

int a = 0; //全局初始化区
char *p1; //全局未初始化区
int main()
{
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //p3在栈上,123456在常量区
static int c = 0; //全局(静态)初始化区
p1 = (char*)malloc(10);
p2 = (char*)malloc(20);
//分配得来的10和20字节的区域在堆区
strcpy(p1, "123456");
//123456放在常量区,编译器可能会将
//它与p3所指向的123456优化成一个地方
}

堆和栈的理论知识如下:

1.申请方式

  栈:由系统自动分配

  堆:需要程序员自己申请,并指明大小,在c中用malloc函数,c++中用new运算符。如p1 = (char *)malloc(10),但是p1本身是在栈内的

2.申请后系统的响应

  栈:只要栈的剩余空间大于所申请空间,系统将为程序提供内存,否则将报异常提示栈溢出。

  堆:首先应该知道操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序。对于大多数系统,会在这块内存空间中的首地址处记录本次申请的大小,这样,代码中的delete语句才能正确得释放本内存空间。另外,由于找到的堆节点的大小不一定正好等于申请的大小,系统会自动的将多余的那部分重新放入空闲链表中。

3.申请大小的限制

  栈:在windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。即栈顶的地址和栈的最大容量是系统预先规定好的,在windows下,栈的大学是2MB,如果申请的空间超过栈的剩余空间,将溢出。因此,能从栈获得的空间较小。

  堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表存储空闲内存地址的,链表的遍历方向是由低地址到高地址。堆的大小受限于计算机系统中有效的虚拟内存。

4.申请效率比较

  栈:由系统自动分配,速度较快。但程序员无法控制

  堆:一般速度较慢,而且容易产生内存碎片。

5.堆和栈的存储内容

  :在函数调用时,第一个进栈的是主函数的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数。在大多数的c编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量不入栈。当本次函数调用结束后,栈内的变量出栈,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。

  堆:一般是在堆的头部用一个字节存放堆的大小。

6.存取效率的比较

  看上述例子中的讲解。

(最后注意和数据结构中的堆和栈是不同的概念)

posted @ 2012-03-28 17:38  爱也玲珑  阅读(474)  评论(0编辑  收藏  举报