![]() |
1
140
堆栈在这种情况下,堆栈是程序运行时放置数据的后进先出缓冲区。后进先出(LIFO)意味着你放入的最后一件东西总是你取出的第一件东西——如果你在堆栈上推两个项目,“A”,然后是“B”,那么你从堆栈中弹出的第一件事就是“B”。 当您在代码中调用函数时,函数调用后的下一条指令将存储在堆栈上,以及可能被函数调用覆盖的任何存储空间。您调用的函数可能会为其自身的局部变量使用更多堆栈。完成后,它释放了它使用的局部变量堆栈空间,然后返回到上一个函数。 堆栈溢出堆栈溢出是指堆栈占用的内存比程序应该使用的内存多。在嵌入式系统中,堆栈可能只有256个字节,如果每个函数占用32个字节,那么你只能调用8个深度函数——函数1调用函数2,函数3调用函数4。…调用函数8的人调用函数9,但函数9会覆盖堆栈外的内存。这可能会覆盖内存、代码等。 许多程序员犯了这个错误,首先调用函数A,然后调用函数B,接着调用函数C,最后调用函数A。它可能在大多数时候都能工作,但只要有一次错误的输入,它就会永远陷入那个循环,直到计算机认识到堆栈被夸大。 递归函数也是导致这种情况的原因之一,但如果你递归编写(即你的函数调用自己),那么你需要意识到这一点,并使用静态/全局变量来防止无限递归。 一般来说,你使用的操作系统和编程语言会管理堆栈,这超出了你的控制范围。你应该查看你的调用图(一个树形结构,从你的main中显示每个函数调用的内容),看看你的函数调用有多深,并检测不想要的循环和递归。有意循环和递归需要人工检查,如果它们相互调用的次数太多,就会出错。 除了良好的编程实践、静态和动态测试之外,在这些高级系统上你无能为力。 嵌入式系统在嵌入式世界中,特别是在高可靠性代码(汽车、飞机、航天)中,您需要进行广泛的代码审查和检查,但您还需要执行以下操作:
高级语言和系统但在操作系统上运行的高级语言中:
Web服务器这取决于你拥有的“沙盒”,你是否可以控制甚至看到堆栈。很有可能,你可以像对待其他高级语言和操作系统一样对待网络服务器——这在很大程度上不在你的掌握之中,但请检查你正在使用的语言和服务器堆栈。它 是 例如,可能会破坏SQL服务器上的堆栈。 |
![]() |
2
9
实际代码中的堆栈溢出很少发生。它发生的大多数情况都是重复发生的,终止已被遗忘。然而,它可能很少出现在高度嵌套的结构中,例如特别大的XML文档。这里唯一真正的帮助是重构代码,使用显式堆栈对象而不是调用堆栈。 |
![]() |
3
9
大多数人会告诉你,堆栈溢出是在没有退出路径的递归中发生的——虽然大多数情况下是正确的,但如果你使用足够大的数据结构,即使是适当的递归退出路径也不会对你有所帮助。 在这种情况下,有一些选择:
|
![]() |
4
7
无限递归是导致堆栈溢出错误的常见方法。为了防止——始终确保有一条出口路径 将 被击中。 :-) 另一种获得堆栈溢出的方法(至少在C/C++中)是在堆栈上声明一些巨大的变量。
这样就行了。 |
![]() |
5
6
除了从直接递归中得到的堆栈溢出形式(例如
这通常发生在响应事件而调用的函数中,但这些函数本身可能会生成新的事件,例如:
在这种情况下,呼叫
|
![]() |
6
4
我重新创建了堆栈溢出问题,同时得到了一个最常见的斐波那契数,即1、1、2、3、5……因此计算fib(1)=1或fib(3)=2…fib(n)=??。 对于n,假设我们感兴趣——如果n=100000,那么相应的斐波那契数是多少?? 单循环方法如下-
这很简单,结果是-
现在,我应用的另一种方法是通过递归的Divide和Concur 即Fib(n)=Fib(n-1)+Fib(n-2);n-2…..直到2&1.其被编程为-
当我运行n=100000的代码时,结果如下-
您可以在上面看到StackOverflowError已创建。现在,这是因为递归次数太多-
因此,堆栈中的每个条目都会创建2个条目,以此类推……表示为-
最终将创建如此多的条目,以至于系统无法在堆栈中处理,并抛出StackOverflowError。 预防: 对于上述示例透视图
|
![]() |
7
4
通常,堆栈溢出是无限递归调用的结果(考虑到当今标准计算机中通常的内存量)。 当你调用一个方法、函数或过程时,进行调用的“标准”方式包括:
因此,通常这需要几个字节,取决于参数的数量和类型以及机器架构。 然后你会看到,如果你开始进行递归调用,堆栈将开始增长。现在,堆栈通常以与堆相反的方向增长的方式保留在内存中,因此,给定大量调用而没有“返回”,堆栈开始变满。 现在,在旧时代,堆栈溢出可能只是因为您耗尽了所有可用内存而发生的,就像这样。对于超出范围的虚拟内存模型(在X86系统上高达4GB),因此通常,如果您遇到堆栈溢出错误,请查找无限递归调用。 |
![]() |
8
2
考虑到这被标记为“黑客攻击”,我怀疑他所指的“堆栈溢出”是一种调用堆栈溢出,而不是像这里大多数其他答案中提到的更高级别的堆栈溢出。它并不真正适用于任何托管或解释环境,例如。NET、Java、Python、Perl、PHP等,这些web应用程序通常是用这些语言编写的,所以你唯一的风险是web服务器本身,它可能是用C或C++编写的。 看看这个帖子: https://stackoverflow.com/questions/7308/what-is-a-good-starting-point-for-learning-buffer-overflow |
![]() |
9
1
当程序用完整个堆栈时,就会发生堆栈溢出。最常见的情况是,你的程序有一个递归函数,它会永远调用自己。每次对递归函数的新调用都需要更多的堆栈,直到你的程序最终用完整个堆栈。 |