1

我已经为此解决方案进行了很多搜索,但完全没有运气。

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

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

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

基本上,我怎样才能永远运行一个函数而不会导致堆栈溢出?

4

2 回答 2

3

堆栈的大小是有限的。在某些 Windows 系统上,它是 1 MB。您可以以编程方式更改堆栈大小,但通常这是一个坏主意。

每个线程都有不同的堆栈。堆栈变量总是在作用域结束时被释放。例如

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
}

在任何时候,上述代码最多只有mouse, i, x, 和cow在堆栈上。如果你使用递归,你可能会得到一个非常深的堆栈,它会溢出。例如

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

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

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

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

有关堆栈上分配过多的更详细示例,请参阅此问题

溢出堆栈的最后也是最有创意的方法是破坏程序状态,使程序变得非常混乱并且无法清理堆栈。通常,您通过使用导致未定义行为的语言特性来做到这一点,如下所示:

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

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

于 2012-12-13T16:59:21.487 回答
2

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

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

PS:这很有趣,我们正在谈论stackoverflow上的stackoverflow:P

于 2012-12-13T16:59:19.017 回答