什么是堆栈溢出?

35 language-agnostic stack-overflow stack

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

vic*_*ugo 26

来自维基百科:

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

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

同样在堆栈中的目的是存储局部变量,因此如果局部变量太大,则更有可能堆栈没有空间来存储它,如果是这种情况也会发生堆栈溢出.

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

堆栈图

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

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

  • @thebrokencube:写一个没有良好退出条件的递归函数,你会发现任何给定语言的堆栈溢出,我会说,垃圾收集与否. (5认同)
  • @thebrokencube:堆栈与垃圾收集没有任何关系.现代应用程序具有更大的堆栈,这使得堆栈溢出的可能性略微降低,但除此之外没有任何区别. (3认同)
  • @FredrikMörk - 好吧,除非它的尾部是递归的,你的语言会进行尾调优化.;) (2认同)

Sco*_*ham 18

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

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

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

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

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

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


Guf*_*ffa 7

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

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

public int Length {
   get {
      return Length;
   }
}
Run Code Online (Sandbox Code Playgroud)

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

public bool Odd(int value) {
   if (value == 0) {
      return false;
   } else {
      return !Odd(value - 1);
   }
}
Run Code Online (Sandbox Code Playgroud)

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

  • 两个示例中堆栈溢出的原因是递归.但是,确实存在另一个非常简单的原因:如果在堆栈上分配的(局部)变量或函数参数太大,通常会在数组中发生这种情况,请参阅http://en.wikipedia.org/wiki/Stack_overflow (3认同)

Fer*_*anB 6

维基百科,couse:

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