Programming  >  C/C++  >  Stack Overflow(堆栈溢出) 
Stack Overflow(堆栈溢出)是程序调试中比较麻烦的一种错误。但总结一下,引起这种错误的原因大致就是两种:
变量申请大空间内存。 递归。  
出错时,弹出下面提示框:
<img class="aligncenter size-full wp-image-440" alt="stackoverflow" src="http://7xwcvs.com1.z0.glb.clouddn.com/wp-content/uploads/2014/04/stackoverflow.png" width="517" height="253" /> 
其中,0x5ad95ad9的值依具体情况而不同。OxC00000FD是错误标号;  
一、局部数组变量空间太大,如下: 
 
 
 
int main(int argc, char* argv[])                
{ 
    char stack_overflow[1024*1024*5];            
    stack_overflow[0] = 1;          
    return 0;     
} 
 
 
 
 
 
 
解决这类问题的办法有两个,一是增大栈空间 (后文中有详细描述),二是改用动态分配 ,使用堆(heap)而不是栈(stack)。
增大栈空间:
<img class="aligncenter size-full wp-image-779" alt="increasestack" src="http://7xwcvs.com1.z0.glb.clouddn.com/wp-content/uploads/2014/04/QQ截图20140401222017.png" width="760" height="555" /> 
在 Visual Studio 开发环境中设置此链接器选项 
打开此项目的“属性页”对话框。(快捷键Alt+F7) 
单击“链接器”选项。 
单击“系统”属性页。 
修改两个属性中的任一个:“堆栈提交大小”   “ 堆栈保留大小”  
 
以下是MSDN中的说明: 
/STACK(堆栈分配) 
 
 
/STACK:<i>reserve</i>[,<i>commit</i>]   //此为命令格式 用在“链接器”中的“命令行”属性页 通过输入命令调整                        
 
 
 
 
 
 
/STACK 选项设置堆栈的大小(以字节为单位 )。此选项仅在生成 .exe 文件时使用。
reserve (保留)值指定虚拟内存中的总的堆栈分配。对于 x86 和 x64 计算机,默认堆栈大小为 1 MB。在 Itanium 芯片组上,默认大小为 4 MB。
commit (提交)取决于操作系统所作的解释。在 Windows NT 和 Windows 2000 中,它指定一次分配的物理内存量。提交的虚拟内存导致空间被保留在页面文件中。更高的 commit 值在应用程序需要更多堆栈空间时可节省时间,但会增加内存需求并有可能延长启动时间。对于 x86 和 x64 计算机,默认提交值为 4 KB。在 Itanium 芯片组上,默认值为 16 KB。
以十进制或 C 语言表示法指定 reserve  值和 commit 值。
设置堆栈大小的另一种方法是使用模块定义 (.def) 文件中的 STACKSIZE 语句。如果两者都指定,则 STACKSIZE  重写堆栈分配 (/STACK) 选项。可以使用 EDITBIN 工具在生成 .exe 文件之后更改堆栈大小。
 函数出现无限递归调用或者递归层次太深: 
如:
 
 
void infinite_loop()     
{ 
    infinite_loop();     
} 
 
int main(int argc, char* argv[])                
{ 
    infinite_loop();     
    return 0;     
} 
 
 
 
 
 
 
又或者如我今天写的递归中因为考虑不周(MaxOfNode超出某个阈值以致SumOfNode永远无法达到MaxOfNode)导致出错:
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
 
 
void Graph::CreateGraph()       
{ 
 tempGraphNodePosition.x = Ogre::Math::RangeRandom(-5,5);                   
 tempGraphNodePosition.y = Ogre::Math::RangeRandom(0,10);                  
 tempGraphNodePosition.z = Ogre::Math::RangeRandom(-5,5);                   
 if(SumOfNode != MaxOfNode)         
 {  
 if(tempGraphNodePosition.squaredDistance(RootNode.position) <= Radius*Radius)                  
 {  
 
 for(std::vector<GraphNode>::const_iterator itr = GraphNodeSet.begin();itr!=GraphNodeSet.end();++itr)                                
 {  
 if (tempGraphNodePosition.squaredDistance(itr->position) < minDistance)                 
 {  
 break;   
 }  
 else if((itr+1) == GraphNodeSet.end())                   
 {  
 GraphNode tempGraphNode;    
 tempGraphNode.position = tempGraphNodePosition;         
 GraphNodeSet.push_back(tempGraphNode);        
 ++SumOfNode;    
 break;   
 }  
 }  
 }  
 return CreateGraph();       
 }  
 else  
 return;   
} 
 
 
 
 
 
 
实际应用中,往往由于粗心大意或者函数间的相互调用而造成了这样的结果。解决的办法当然是找到使用递归的地方,并消除BUG。
建议看完此篇接着看《递归中隐藏的陷阱 Stack Overflow》