1. 数据结构上:
栈:在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域。这句话的意思是栈顶的地址和栈的最大容量是系统预先规定好的,在 WINDOWS下,栈的大小是1M(也有的说是2M,总之是一个编译时就确定的常数),如果申请的空间超过栈的剩余空间时,将提示overflow。因此,能从栈获得的空间较小。
堆:堆是向高地址扩展的数据结构,是不连续的内存区域。这是由于系统是用链表来存储的空闲内存地址的,自然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存,一般32位程序拥有4G虚拟内存空间。由此可见,堆获得的空间比较灵活,也比较大。
2. 存储内容上:
栈的存储内容: 在主函数中调用次级函数时,首先进栈的是主函数的下一条指令的地址(紧跟次级函数调用语句的下一条可执行语句),如果在次级函数中定义的数组过大,导致堆栈分配失败时,编译器会直接跳过次级函数的执行,将出错箭头指向该次级函数调用语句的下一条语句,就是这个原因;然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
堆的存储内容:由申请堆空间的程序员指定。
3. 对比总结:
从 以上知识可知,栈是操作系统提供的功能,特点是快速高效,缺点是有限制,数据不灵活;而堆是C/C++函数库提供的功能,特点是灵活方便,数据适应面广泛,但是效率有一定降低。
栈是系统数据结构,对于进程/线程是唯一的;堆是函数库内部数据结构,不一定唯一。不同堆分配的内存逻辑上无法互相操作。
栈空间分静态分配和动态 分配两种。静态分配是编译器完成的,比如自动变量(auto)的分配。动态分配由alloca函数完成。栈的动态分配无需释放(是自动的),也就没有释放 函数。为可移植的程序起见,栈的动态分配操作是不被鼓励的!堆空间的分配总是动态的,虽然程序结束时所有的数据空间都会被释放回系统,但是精确的申请/释放内存是良好程序的基本要素。
函数中出现栈溢出的解决方案:
主要有两个办法:
一、 改为堆变量:
int* pa = malloc(sizeof(int)*1000*1000);
然后可以将pa当数组用。(数组和指针在C里基本等同)
当然,不用了记得free。
二 修改系统限制
这个栈变量= 1000*1000*4≈4M。
如果这个函数不频繁调用,也不递归,一般还是可以接受。
可以适当增加编译器的栈(堆栈)空间,来解决栈溢出问题。
当然方法二非常不值得推荐
在VS2013中解决步骤:
· 右键打开项目的“属性页”对话框。
· 单击“链接器(Linker)”文件夹。
· 单击“系统 (System)”属性页。
· 修改下列任意一个(都改也可以)属性:
总结:除非特别要求,开一个容量过大的数组,是很不明智的!