您的位置:首页 > 理论基础

关于堆和栈的一点理解

2014-05-30 11:44 302 查看
一、一个由C++/C编写的程序的内存是怎么分配的?
栈区(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语句才能正确释放本内存空间 。 如果找到的堆结点大于所申请的空间,系统会将多余的部分重新放入空闲链表中。
最后用一个我看到的一个经典的比喻作结:
使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等 准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小;使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度大。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息