现象:
在一个类的头文件中定义了一个数组
编译后出现:
stack overflow,堆栈溢出
(下文中,stack=栈=堆栈)
这次在写一个程序的时候,定义了一个比较大的int数组,发现大概元素个数超过25W个的时候,程序就不正常了,如果个数再多,还可能出现一个Windows错误,然后问要不要发送错误报告.
以前我也碰到过这个问题,不过一直就没去想怎么解决.今天突然一时兴起,就用单步调试试了一下,定义数组的时候没问题,但是在开始对数组赋值的时候,就会弹出一个Stack OverFlow的错误提示,有了程序的错误提示,那就好解决了,在百度上搜索了一下,就找到了解决方法.
如果是英文版:
project -> setting -> link -> category 选择 output -> stack allocations 里面的 reserve 填入 0x10000000 然后选OK
如果是创天中文版:
工程 -> 配置 -> link -> "分类" 选择 Output -> "叠存分配" 里面的 "保留" 填入 0x10000000 然后选"确定" ("叠存",我汗,这个创天中文是那个sb翻译的....)
=========================下面是一些自己的分析,不保证正确,没兴趣可以不看了======================
据我的理解,这个地方就是设置堆栈的大小,上面输入的数字,如果单位是Byte的话,那就有2^28B,也就是256MB,如果单位是bit,那也有32MB.再算一下,VC中一个int是占用4B,那么应该可以有2^26B(6KW+)或者2^23B(800W+)个元素,经过测试(我的256MB内存的电脑接近死机....),可以证实,数组元素可以达到6KW个,如果7KW个的话,会出现stack overflow的错误.
这么说来,那个设置的数值的单位就是Byte了,而原来的stack大小,应该是4B*26W,约1MB.
再分析一下汇编后的代码:
26: int s[MAX];
27: s[0]=1;
00401202 mov dword ptr [ebp-0FC00000h],1
其中MAX=0x03F00000
这样可以明显看出,VC就是在stack上分配了0x0FC00000 Byte的空间
值得注意的是,这种扩大stack大小的解决方法,并不是什么时候都能用的,用的不好的话,可能会掩盖一些本来可以发现的错误.
举个例子:学过汇编的都应该知道,调用函数的时候,都有个参数入栈,保存返回地址,和恢复堆栈的过程,而递归函数,多次递归导致的栈空间消耗也是挺大的.有的时候,如果函数写的不对,或者其它什么原因,可能导致占用的空间越来越大,最后overflow,而如果人为的扩大stack的大小,可能就会掩盖了这种错误,等到以后不知道什么情况下,问题出现了,这个时候要修改可能就晚了.
所以,我的意思就是,除非能确定的知道,"程序确实需要扩大stack空间,需要扩大多少,这些扩展的空间用来干什么".不然还是使用默认的1MB stack空间就行了