堆栈最终会溢出吗?

时间:2012-12-13 16:50:17

标签: c++ memory dynamic stack-overflow

我已经搜索了很多这个解决方案,但根本没有运气。

这是我的程序的基础知识。我的主要功能中有一个循环。循环需要计算大量数据,并且当我给我的一个变量一个大于20的值时,它最终会堆栈溢出。

我知道,无论何时你在函数中“返回”它都会释放整个堆栈。这就是事情,我需要这个循环永远运行,直到该人关闭应用程序。

这甚至可能吗?堆栈溢出发生之前,所有功能是否都需要较短的寿命?如果我使用动态内存,我仍然无法摆脱它在运行时累积的其他堆栈数据。

基本上,如何永远运行一个函数而不会导致堆栈溢出?

2 个答案:

答案 0 :(得分:3)

堆栈的大小有限。在某些Windows系统上它是1 MB。你可以programatically change the stack size,但这往往是个坏主意。

每个线程都有不同的堆栈。堆栈变量始终在范围的末尾释放。 E.g。

void MyFunction
{ // begin of scope 1
    std::string mouse("feep"); 
    for (int i = 0; i < 10000000; i++)
    { // begin of scope 2
        int x = 1;  // x is on the stack
        std::string cow("moo"); // cow is on stack
      // end of scope 2, cow is destroyed then the stack is freed for cow and x before the next iteration of the loop begins
    } 
    return; // end of scope 1, mouse is destroyed ant the stack is freed for mouse
}

在任何时候,上述代码最多都会在堆栈中包含mouseixcow。如果你使用recursion,你可以最终得到一个非常深的堆栈,它会溢出。 E.g。

void StackOverflowIncoming()
{ // begin of scope
    int aVariableOnTheStack = 0;
    StackOverflowIncoming();
    // end of scope
}

上面的函数永远打开新的作用域,永远不会留下作用域,所以在某些时候它会溢出。

溢出堆栈的另一种方法是alloca,它直接分配堆栈(然后在分配的范围关闭后立即释放。只需使用alloca分配10 MB堆栈,如果最大堆栈大小为1 MB。这也可以通过在堆栈上分配一个巨大的结构来实现。

void InstantStackOverflow()
{
    char buffer[1<<24];
}

有关分配的更详细示例,请参阅此question

溢出堆栈的最后和最有创意的方法是破坏程序状态,以便程序可怕地混淆并且无法清理堆栈。通常,您通过使用导致未定义行为的语言功能来执行此操作,如下所示:

void TryToCorruptTheStack()
{ // begin of scope
    char buffer[1];
    for (int i = -20; i < 20; i++)
        buffer[i] = 5;
    // end of scope
}

有关堆栈损坏的更详细示例,请参阅此question

答案 1 :(得分:2)

运行函数不会填满堆栈。但是,如果您正在使用递归函数调用,是的,最终堆栈将溢出。回到你的问题 - 你说你在main函数中运行一个循环导致堆栈溢出然后你说调用函数导致stackoverflow。循环不会导致堆栈溢出,除非您在其中创建新对象!同样,在C / C ++中,主函数不能被称为递归。你不是一个好朋友。

如果您可以共享一些示例代码,那就太棒了。

PS:很有意思,我们在讨论stackoverflow上的stackoverflow:P