什么是堆栈溢出?

时间:2009-07-10 15:14:44

标签: language-agnostic stack stack-overflow

什么是堆栈溢出错误?它可能会出现什么类型的程序/编程语言?是否不太可能在Web应用程序代码中出现?

7 个答案:

答案 0 :(得分:26)

来自Wikipedia

  

在软件中,发生堆栈溢出   当使用太多内存时   调用堆栈。在许多编程中   语言,调用栈包含一个   通常有限的记忆   确定在开始时   程序

堆栈是一种数据结构,它记录程序的子程序在完成执行时应该返回控制的点。当子程序被调用时,返回地址在堆栈中被推送,当子程序完成执行时,返回地址从堆栈中被。如果有很多子程序且堆栈中没有空间,则会发生堆栈溢出。

此外,堆栈中还存储局部变量,因此如果局部变量太大,则堆栈可能没有空间来存储它,如果是这种情况,也会发生堆栈溢出。

维基百科包含一个很好的图表,当从另一个名为DrawLine的子例程调用DrawSquare子例程时,该图表描述了堆栈。我希望这张图片有助于更好地理解堆栈结构。

stack diagram

堆栈溢出有两个主要原因:深度函数递归过大的堆栈变量。由于这些是几乎所有编程语言中的常用术语,因此除了语言的复杂性之外,还可能发生堆栈溢出。

Guffa贡献:堆栈与垃圾收集没有任何关系。现代应用程序具有更大的堆栈,这使得堆栈溢出的可能性略微降低,但除此之外没有差别。

答案 1 :(得分:18)

堆栈包含许多堆栈帧并存储在内存中。 每次调用函数时,都会向堆栈添加新的堆栈帧。堆栈帧包含要传递给被调用函数的参数和返回地址,这样当被调用函数完成时,cpu知道返回的位置,因此它可以继续执行调用函数。堆栈帧还可以包含要被调用的函数的局部变量使用的内存。

在此示例中,Main函数名为WriteCustomerDetails,并调用PrintToConsole来写出WriteCustomerDetails函数查找的各个数据位:

'=======堆栈顶部====================='
功能:PrintToConsole
Arg:John Smith,34 Acacia Avenue,23岁 “------------------------------------------------- ----------“
功能:WriteCustomerDetails
Arg:John Smith “------------------------------------------------- ----------“
功能:主要
'======堆栈底部==================='

如果没有保留堆栈的足够空间,则会发生堆栈溢出。通常堆栈位于一个大的连续内存块中,因此不会分成块,这意味着需要一块大内存,这使得运行时很难尝试增加为堆栈保留的空间如果它填满了。

当意外写入调用自身的函数时,通常会发生堆栈溢出。有时,只要函数中有一个“if”或某些条件在某个时刻停止调用,函数就可以调用自身。这称为递归函数。但是,如果没有停止并且函数一直在调用自身,或者两个或多个函数可能一直在相互调用,那么它们很快就会占用所有堆栈内存。当没有剩下的时候,你得到一个堆栈溢出,程序崩溃。

这可能发生在任何程序中,它们不一定非常复杂,并且可能发生在运行网站的代码中。而且,它也可以在脚本语言中出现。

答案 2 :(得分:7)

当您使用过多的堆栈空间时,会发生堆栈溢出。发生这种情况通常有两种情况:

第一个是代码中出现错误,导致没有退出的递归循环。例如,一个属性读取自己:

public int Length {
   get {
      return Length;
   }
}

第二个是你有一个太深的递归循环。由于堆栈空间有限,您只能将算法嵌套一定次数。如果您的算法嵌套太深,以至于它在堆栈空间存在之前耗尽,则会出现堆栈溢出。例如:

public bool Odd(int value) {
   if (value == 0) {
      return false;
   } else {
      return !Odd(value - 1);
   }
}

如果使用太大的值调用此方法,它将嵌套太深并导致堆栈溢出。

答案 3 :(得分:6)

来自wikipedia,来自:

  

在软件中,当调用堆栈上使用了太多内存时,会发生堆栈溢出。在许多编程语言中,调用堆栈包含有限的内存量,通常在程序开始时确定。调用堆栈的大小取决于许多因素,包括编程语言,机器架构,多线程和可用内存量。当在调用堆栈上使用太多内存时,堆栈被称为溢出;通常导致程序崩溃。1这类软件错误通常是由两种类型的编程错误引起的

答案 4 :(得分:1)

当您使用堆栈(duh ...)并且存在内存分配/读取问题时,会发生堆栈溢出。在“网络程序”中,正如你所说的(我假设你在谈论HTML,PHP,JS),要么你不使用堆栈,要么使用的语言不允许低级别的内存控制来防止这些问题。

答案 5 :(得分:0)

分配给堆栈的内存用完后,系统将引发堆栈溢出错误。

注意: 堆栈是仅允许推入和弹出的存储器。 您不能在两者之间访问值。 它遵循LIFO。

答案 6 :(得分:0)

当堆栈逻辑结构在没有基本/终止条件的情况下通过递归方法调用变得太满时,就会发生堆栈溢出。在典型的程序中,原始变量(例如整数,浮点数等)存储在物理内存中,而方法调用存储在逻辑数据结构(如堆栈)中。堆栈以后进先出(LIFO)的方式存储数据。

Main(){ 
 foo(3); 
 } 

 foo(n){
  if(n<1) // recursion with base condition that terminates when n<1
   return;
  else foo(n-1); 
  print ('Hello' + n);
 }

enter image description here

在没有基本条件if(n<1) return的情况下,方法foo(n)将递归调用自身,直到堆栈中没有更多空间,从而导致堆栈溢出。

相关问题