我已经搜索了很多这个解决方案,但根本没有运气。
这是我的程序的基础知识。我的主要功能中有一个循环。循环需要计算大量数据,并且当我给我的一个变量一个大于20的值时,它最终会堆栈溢出。
我知道,无论何时你在函数中“返回”它都会释放整个堆栈。这就是事情,我需要这个循环永远运行,直到该人关闭应用程序。
这甚至可能吗?堆栈溢出发生之前,所有功能是否都需要较短的寿命?如果我使用动态内存,我仍然无法摆脱它在运行时累积的其他堆栈数据。
基本上,如何永远运行一个函数而不会导致堆栈溢出?
答案 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
}
在任何时候,上述代码最多都会在堆栈中包含mouse
,i
,x
和cow
。如果你使用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