关于堆和栈的一点理解
2014-05-30 11:44
302 查看
一、一个由C++/C编写的程序的内存是怎么分配的?
栈区(stack):
编译器自动分配,存放函数中的参数值,局部变量的值。
堆区(heap):
一般由程序员自动分配和释放,在C中用malloc函数,在C++中用new关键字,若程序员不释放,则在程序结束时可能由OS自动回收。注意它与数据结构中的堆是两个概念。
全局区(静态区)(static):
存放全局变量和静态变量,初始化的全局变量和静态变量放在一块区间,未经初始化的全局变量和静态变量则放在相邻的另一块区间,程序结束后由系统自动释放。
文字常量区:
存放常量字符串,程序结束后由系统自动释放。
程序代码区:
存放函数体的二进制代码。
二、一个简单而经典的例子
栈:只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则提示栈溢出。注意: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。静态变量是不入栈的;当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆:操作系统有一个记录空间空闲地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请的空间的堆结点,然后将该节点从空闲链表中删除,并且将该节点分配给程序。此时,大多数的系统会在这块内存空间中的首地址处记录本次分配的大小,只有这样delete语句才能正确释放本内存空间 。 如果找到的堆结点大于所申请的空间,系统会将多余的部分重新放入空闲链表中。
最后用一个我看到的一个经典的比喻作结:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等 准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小;使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
栈区(stack):
编译器自动分配,存放函数中的参数值,局部变量的值。
堆区(heap):
一般由程序员自动分配和释放,在C中用malloc函数,在C++中用new关键字,若程序员不释放,则在程序结束时可能由OS自动回收。注意它与数据结构中的堆是两个概念。
全局区(静态区)(static):
存放全局变量和静态变量,初始化的全局变量和静态变量放在一块区间,未经初始化的全局变量和静态变量则放在相邻的另一块区间,程序结束后由系统自动释放。
文字常量区:
存放常量字符串,程序结束后由系统自动释放。
程序代码区:
存放函数体的二进制代码。
二、一个简单而经典的例子
//main.cpp int a = 0; //全局初始化区 char *p1; //全局未初始化区 main() { int b;// 栈区 char s[] = "abc"; //栈区 char *p2;// 栈区 char *p3 = "123456"; 123456/0 在常量区,p3在栈上。 static int c =0; 全局(静态)初始化区 p1 = (char *)malloc(10); p2 = (char *)malloc(20); //分配得来得10和20字节的区域就在堆区。 strcpy(p1, "123456"); 123456/0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。 }三、关于堆栈申请后的响应
栈:只要栈的剩余空间大于所申请的空间,系统将为程序提供内存,否则提示栈溢出。注意: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。静态变量是不入栈的;当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆:操作系统有一个记录空间空闲地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请的空间的堆结点,然后将该节点从空闲链表中删除,并且将该节点分配给程序。此时,大多数的系统会在这块内存空间中的首地址处记录本次分配的大小,只有这样delete语句才能正确释放本内存空间 。 如果找到的堆结点大于所申请的空间,系统会将多余的部分重新放入空闲链表中。
最后用一个我看到的一个经典的比喻作结:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等 准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小;使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
相关文章推荐
- 关于BMP图片的一点理解,读取图象数据到数组
- 关于反射的一点理解(一)
- 关于DataRow和DataColumn的一点个人简单理解
- us/os ii 学习笔记 20100421 关于os的一点宏观理解
- 关于AS3中弱引用的一点理解(转载)
- 关于DataRow和DataColumn的一点个人简单理解
- 关于Action的一点理解
- 我的一点浅见——关于机器的理解
- 一个草根关于OO的一点理解
- 关于AS3中弱引用的一点理解
- 关于equals()和==操作的一点理解
- 关于DataRow和DataColumn的一点个人简单理解-.NET教程,数据库应用
- 关于KMP算法的一点个人理解
- 关于龙芯拿MIPS授权的一点理解
- 关于openlayers中namespace的一点理解
- 关于Ndis驱动的一点个人理解
- 关于AS3中弱引用的一点理解
- 关于DataRow和DataColumn的一点个人简单理解
- 关于博弈论中的共同知识的一点理解
- 关于unix下实际用户ID、有效用户ID、设置用户ID、文件所有者ID的一点理解