【问题标题】:Stack overflow at runtime运行时堆栈溢出
【发布时间】:2021-05-28 00:28:35
【问题描述】:

如果编译器在运行前计算出所需的堆栈大小,那么堆栈溢出是如何发生的呢? 编译时编译器是否计算整个程序的堆栈所需的内存总量?

【问题讨论】:

  • 编译器计算过程中可能会出现栈溢出。我认为典型的编译器不会进行计算。
  • 那么,你有多少堆栈内存?这可能会有所不同。此外,编译器知道每个堆栈帧的大小,但不知道您可能有多少帧。考虑一种递归算法,或在堆栈上动态分配的内存。
  • 一台计算机只有这么多的“堆栈空间”。如果由于某种原因(无限递归、写出数组边界、其他未定义行为)在程序中使用了更多,那么您会得到堆栈溢出
  • “如果我的假设是正确的,为什么事实与我的假设相矛盾?”这个问题的答案通常是假设是不正确的。

标签: c++


【解决方案1】:

没有。

编译器只能在非常有限的范围内知道运行时发生的事情。例如,它无法判断执行以下函数需要多少堆栈:

void foo() {
    int x = 0;
    std::cin >> x;
    if (x == 42) foo();
}

堆栈是一种有限的资源,如果超过它,就会出现堆栈溢出。

【讨论】:

  • 我的问题是,是否有针对这些异常情况的预防程序?也许分配给堆?
  • @StreamlineAstra 但是不,您无法防止堆栈溢出,因为您通常无法确定以何种顺序调用哪些函数。嗯,理论上是可以的,但是由未知事件决定的程序流程就很难了。
【解决方案2】:

考虑这个非常简化的示例函数(伪代码)

 void Foobar(long nested) {
    if( --nested >= 0)
        Foobar(nested);
 }

每次调用都会(至少)将返回地址压入堆栈。

问题:您需要多少内存?

没错。就是这个原因。

【讨论】:

    【解决方案3】:

    编译器通常会知道每个函数需要多少堆栈内存,但在编译时无法知道调用了哪些函数。所以你可能会得到一堆超出堆栈内存的函数调用。

    此外,堆栈内存可以在进程或线程之间更改,因此编译器在编译时不知道限制。

    最后,您可以在堆栈上动态分配内存。这是通过递归或使用 C 中的 alloca 之类的调用来完成的。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-09-11
      • 2018-01-28
      • 2010-12-22
      • 2012-09-29
      • 2019-05-18
      • 2023-03-03
      • 2016-05-15
      相关资源
      最近更新 更多