我已经为此解决方案进行了很多搜索,但完全没有运气。
这是我的程序的基础知识。我的主要功能中有一个循环。循环需要计算大量数据,当我给我的一个变量一个大于 20 的值时,它最终会堆栈溢出。
我知道,无论何时您在函数中“返回”,它都会释放整个堆栈。事情是这样的,我需要这个循环永远运行,直到人们关闭应用程序。
这甚至可能吗?在堆栈溢出发生之前,所有函数都需要很短的生命周期吗?如果我使用动态内存,我仍然无法摆脱它在运行时积累的其他堆栈数据。
基本上,我怎样才能永远运行一个函数而不会导致堆栈溢出?
我已经为此解决方案进行了很多搜索,但完全没有运气。
这是我的程序的基础知识。我的主要功能中有一个循环。循环需要计算大量数据,当我给我的一个变量一个大于 20 的值时,它最终会堆栈溢出。
我知道,无论何时您在函数中“返回”,它都会释放整个堆栈。事情是这样的,我需要这个循环永远运行,直到人们关闭应用程序。
这甚至可能吗?在堆栈溢出发生之前,所有函数都需要很短的生命周期吗?如果我使用动态内存,我仍然无法摆脱它在运行时积累的其他堆栈数据。
基本上,我怎样才能永远运行一个函数而不会导致堆栈溢出?
堆栈的大小是有限的。在某些 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
}
有关堆栈损坏的更详细示例,请参阅此问题。
运行函数不会填满堆栈。但是,如果您使用递归函数调用,是的,最终堆栈会溢出。回到你的问题 - 你说你正在主函数中运行一个导致堆栈溢出的循环,然后你说调用函数导致堆栈溢出。除非您在其中创建新对象,否则循环不会导致堆栈溢出!同样,在 C/C++ 中,主函数不能被称为递归。你不是很清楚的朋友。
如果您可以分享一些示例代码,那就太好了。
PS:这很有趣,我们正在谈论stackoverflow上的stackoverflow:P