35

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

4

7 回答 7

26

来自维基百科

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

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

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

Wikipedia 包含一个漂亮的图表,描绘了DrawLine从另一个名为 的子程序调用子程序时的堆栈DrawSquare,我希望这张图片有助于更好地理解堆栈结构。

堆栈图

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

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

于 2009-07-10T15:19:28.253 回答
18

堆栈包含许多堆栈帧并存储在内存中。每次调用函数时,都会在堆栈中添加一个新的堆栈帧。堆栈帧包含要传递给被调用函数的参数和返回地址,这样当被调用函数完成时,cpu 知道返回到哪里,以便继续执行调用函数。堆栈帧也可能包含被调用函数的局部变量使用的内存。

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

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

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

当意外编写调用自身的函数时,通常会发生堆栈溢出。有时函数调用自身是可以的,只要函数中有一个“if”或某个条件在某个点停止调用。这称为递归函数。但是,如果没有停止并且函数不断地调用自己,或者两个或多个函数不断地相互调用,那么它们很快就会吃掉所有的堆栈内存。当没有剩余时,您会遇到堆栈溢出并且程序崩溃。

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

于 2009-07-10T15:37:12.327 回答
7

当您使用太多堆栈空间时会发生堆栈溢出。出现这种情况一般有两种情况:

第一种是当您在代码中出现错误时,会导致没有退出的递归循环。例如从自身读取的属性:

public int Length {
   get {
      return Length;
   }
}

第二个是当你有一个太深的递归循环时。由于堆栈空间有限,您只能将算法嵌套一定次数。如果你的算法嵌套太深,以至于它在存在之前就用完了堆栈空间,你就会得到堆栈溢出。例子:

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

如果调用这个方法的值太大,会嵌套太深,导致堆栈溢出。

于 2009-07-10T15:39:31.027 回答
6

来自维基百科,当然:

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

于 2009-07-10T15:19:08.567 回答
1

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

于 2009-07-10T15:19:26.320 回答
0

当分配给堆栈的内存耗尽时,系统将抛出堆栈溢出错误。

注意:堆栈是只允许推送和弹出的内存。您无法访问介于两者之间的值。它遵循后进先出法。

于 2019-07-09T12:58:02.250 回答
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);
 }

在此处输入图像描述

如果没有基本条件if(n<1) return,该方法foo(n)将递归调用自身,直到堆栈中没有更多空间,因此堆栈溢出。

于 2019-11-25T07:39:33.460 回答