解决大数组定义时栈溢出的两种方法

来源:互联网 发布:广州淘宝二手汽车网 编辑:程序博客网 时间:2024/06/05 06:29

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*44M

如果这个函数不频繁调用,也不递归,一般还是可以接受。

可以适当增加编译器的栈(堆栈)空间,来解决栈溢出问题。

当然方法二非常不值得推荐

 

VS2013中解决步骤:

· 右键打开项目的“属性页”对话框。

· 单击“链接器(Linker)”文件夹。

· 单击“系统 System)”属性页。

· 修改下列任意一个(都改也可以)属性:

         · 堆栈提交大小Stack Reserve Size 100000000;

         · 堆栈保留大小Stack Commit Size  100000000.

 

总结:除非特别要求,开一个容量过大的数组,是很不明智的!

1 0
原创粉丝点击