[转]C++堆栈溢出的原因以及可⾏的解决⽅法
栈溢出(stackoverflow)的原因及解决办法
⼤家都知道,Windows程序的内存机制⼤概是这样的:全局变量(局部的静态变量本质也属于此范围)存储于堆内存,该段内存较⼤,⼀般不会溢出;
函数地址、函数参数、局部变量等信息存储于栈内存,VC++6中栈内存默认⼤⼩为1M,对于当前⽇益扩⼤的程序规模⽽⾔,稍有不慎就可能出问题(动态申请的内存即new出来的内存不在栈中),即如果函数这样写:
void test_stack_overflow()
{
char *pdata = new[2 * 1024 * 1024];
delete[]pdata;
}
是不会出现这个错误的,⽽这样写则不⾏:
void test_stack_overflow()
{
char chdata[2 * 1024 * 1024];
}
⼤多数情况下都会出现内存溢出的错误,不信在VC++6中随便做个程序,调⽤⼀下这个函数试式。
出现栈内存溢出的常见原因有2个:
1>函数调⽤层次过深,每调⽤⼀次,函数的参数、局部变量等信息就压⼀次栈。
2>局部静态变量体积太⼤
第⼀种情况不太常见,因为很多情况下我们都⽤其他⽅法来代替递归调⽤(反正我是这么做的),所以只要不出现⽆限制的调⽤都应该是没有问题的,起码深度⼏⼗层我想是没问题的,这个我没试过但我想没有谁会把调⽤深度作那么多。检查是否是此原因的⽅法为,在引起溢出的那个函数处设⼀个断点,然后
执⾏程序使其停在断点处,然后按下快捷键Alt+7调出callstack窗⼝,在窗⼝中可以看到函数调⽤的层次关系。
第⼆种情况⽐较常见了,我就是犯了这个错误,我在函数⾥定义了⼀个局部变量,是⼀个类对象,该类中有⼀个⼤数组,⼤概是1.5M。
解决办法⼤致说来也有两种:
1>增加栈内存的数⽬
2>使⽤堆内存增加栈内存
acess数据库第⼀种解决办法:在VC++6种依次选择Project->Setting->Link,在Category中选择output,在Reserved中输⼊16进制的栈内存⼤⼩
如:0x10000000,然后点ok就可以了。
其他编译器也有类似的设置,个⼈认为这不是⼀个好办法,有⼀个致命原因,不知道有没有⼈遇到过,我把栈内存改⼤后,与数据库建⽴不了连接了(ADO⽅式,Acess数据库),还有遇到调⽤CreateThread会提⽰栈不够⽽创建线程失败,把栈内存还原,问题⽴刻消失。
不知道究竟是什么原因,有知道的可以告诉我。
第⼆种解决办法是⽐较可⾏的,具体实现由很多种⽅法可以直接把数组定义改成指针,然后动态申请内存;也可以把局部变量变成全局变量,⼀个偷懒的办法是直接在定义前边加个static,呵呵,直接变成静态变量(实质就是全局变量)。即可以把上例中的函数这么写:
void test_stack_overflow()
{
static char chdata[2 * 1024 * 1024];
}
当然,除⾮万不得已,尽量不要使⽤这么⼤的数组,出现这种情况多半说明程序结构有问题。
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论