什么是堆栈溢出?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了什么是堆栈溢出?相关的知识,希望对你有一定的参考价值。

参考技术A 什么是栈溢出和堆溢出?
所谓溢出广义上就是超出范围,整数就有溢出,比如8字节无符号整数是0到255

0 - 1就是下溢 255 + 1就是上溢

说正题

int f(int x)



int a[10];

a[唬1] = x;



这个就是栈溢出,x被写到了不应该写的地方。在特定编译模式下,这个x的内容就会覆盖f原来的返回地址。也就是原本应该返回到调用位置的f函数,返回到了x指向的位置。一般情况下程序会就此崩溃。但是如果x被有意指向一段恶意代码,这段恶意代码就会被执行。

堆溢出相对比较复杂,因为各种环境堆的实现都不完全相同。但是程序管理堆必须有额外的数据来标记堆的各种信息。堆内存如果发生上面那样的赋值的话就有可能破坏堆的逻辑结构。进而修改原本无法访问的数据。

int f(char *s, int n)



char a[10];

memcpy(a, s, n);

...



这个是栈溢出比较真实一点的例子,如果传入的数据长度大于10就会造成溢出,进而改变f的返回地址。只要事先在特定地址写入恶意代码,代码就会被执行。

堆溢出执行恶意代码的一种情况是通过过长的数据破坏堆结构,使下次申请能得到保存某些特定函数指针的位置,然后进行修改。

栈和堆溢出的一个共性就是第三方可以完全依靠提供特定数据实现代码级别的入侵。玩游戏的话可能知道PSP3000的破解,利用的就是PSP系统显示tiff文件时候的一个溢出漏洞。tiff文件内包含一段入侵代码,载入tiff文件的时候这段代码也会被载入,只不过这个时候各奔不可能被执行。但是tiff中的一部分数据是超长的,并且超长的部分包含了入侵代码的位置。当系统读取这部分数据的时候入侵代码就会被执行。
堆栈溢出是什么意思
堆栈溢出就是不顾堆栈中分配的局部数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了老的堆栈数礌。 或者解释为 在长字符串中嵌入一段代码,并将过程的返回地址覆盖为这段代码的地址,这样当过程返回时,程序就转而开始执行这段自编的代码了。
电脑屏幕上出现(堆栈溢出、位置:第37行)是什么意思
zhidao.baidu/...iST4BK

人家有人有详细解答
堆栈溢出一般是由什么原因导致的?
一般情况下,是读写数据超出来申的内存的范围。

堆栈溢出一般会报段错误
电脑跳出窗口显示堆栈溢出 第一行 是什么意思
常言所说的堆栈溢出,就是指栈溢出。使用 malloc(); 函数是动态分配内存堆区的空间,一般的程序如没用这个,就不存在堆溢出。栈溢出: 栈空间是预设的,它通常用于存放临时变量,如果你在函数内部定义一个局部变量,空间超出了设置的栈空间大小,就会溢出。不仅如此,如果函数嵌套太多,也会发生栈溢出,因为函数没有结束前,函数占用的变量也不被释放,占用了栈空间。解决办法:恰当的设置栈空间大小。分析代码,评估在哪个环节,使用的临时变量字节数最大,所设置的栈空间必须大于此。也可以将大的变量在全局进行定义,它就不占用栈区空间
请问:堆栈溢出是什么意思?怎么处理?
堆栈溢出就是不顾堆栈中分配的局骸数据块大小,向该数据块写入了过多的数据,导致数据越界,结果覆盖了老的堆栈数据。就是字写多了!
堆栈溢出是什么意思
操作系统在内存里分配给你这个程序进程的内存块满足不你的程序的请求了
1001 递归太深;堆栈溢出是什么意思
1001 递归是反复调用,用空间换时间,如果你递归次数太多,内存开销太大了,所以会报错 不ac这个题似乎不用递归就能做啊
堆栈溢出一般是由什么原因导致的?
没有回收垃圾资源。
堆栈溢出一般是由什么原因导致的
申请的内存不够,已经把申请的内存用完了,但还是一直往里放数据。

什么是堆栈溢出?

【中文标题】什么是堆栈溢出?【英文标题】:What is a stack overflow? 【发布时间】:2010-11-09 18:08:32 【问题描述】:

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

【问题讨论】:

en.wikipedia.org/wiki/Stack_overflow 【参考方案1】:

来自wikipedia,当然:

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

【讨论】:

这不是我正在寻找的答案【参考方案2】:

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

【讨论】:

缺乏对内存分配的控制不会防止堆栈溢出。 几乎每种语言都有一个调用堆栈,它是必需的,以便代码可以在子例程结束后返回到它所在的位置。这个调用栈一般是固定大小的,所以调用太多子程序后没有返回,栈满了会溢出。【参考方案3】:

来自Wikipedia:

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

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

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

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

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

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

【讨论】:

据我了解,这在带有垃圾收集功能的现代语言中也不会发生(至少没有那么多,我不太确定)。 当然它可以在脚本语言中发生。它们有一个调用栈,它自然会溢出。 @thebrokencube:编写一个没有良好退出条件的递归函数,并且在任何给定语言中都会出现堆栈溢出,我想说,不管是否收集垃圾。 @thebrokencube:堆栈与垃圾收集没有任何关系。现代应用程序具有更大的堆栈,这使得堆栈溢出的可能性略低,但除此之外没有任何区别。 @Fredrik Mörk - 好吧,除非它是尾递归并且您的语言进行尾调用优化。 ;)【参考方案4】:

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

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

'=======栈顶=====================' 功能:PrintToConsole Arg:约翰·史密斯,34 Acacia Avenue,23 岁 '---------------------------------------------------- ----------' 功能:WriteCustomerDetails Arg:约翰·史密斯 '---------------------------------------------------- ----------' 功能:主 '======栈底===================='

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

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

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

【讨论】:

【参考方案5】:

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

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

public int Length 
   get 
      return Length;
   

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

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

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

【讨论】:

两个示例中堆栈溢出的原因是递归。但是,确实还有另一个非常简单的原因:如果分配在堆栈上的(局部)变量或函数参数太大,通常会发生在数组中,请参阅en.wikipedia.org/wiki/Stack_overflow【参考方案6】:

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

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

【讨论】:

【参考方案7】:

当堆栈逻辑结构因没有基本/终止条件的递归方法调用而变得太满时,就会发生堆栈溢出。在典型的程序中,您的原始变量(例如整数、浮点数等)存储在物理内存中,而您的方法调用存储在逻辑数据结构(例如堆栈)中。堆栈以后进先出序列 (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&lt;1) return,方法foo(n) 将递归调用自身,直到堆栈中没有更多空间,因此堆栈溢出。

【讨论】:

以上是关于什么是堆栈溢出?的主要内容,如果未能解决你的问题,请参考以下文章

什么是堆栈溢出?

函数 堆栈溢出

什么是堆栈溢出和缓冲区溢出错误? [复制]

堆栈溢出一般是由啥原因导致的?

分段错误和堆栈溢出有啥区别?

堆栈和堆溢出利用是啥意思