使用递归溢出堆栈的方法有哪些? 我有一个这样的方式使用递归溢出堆栈
#include <iostream>
void func()
{
int arr[100500];
func();
}
int main()
{
func();
std :: cin.ignore(); std :: cin.get();
return 0;
}
但我不喜欢它。
使用递归溢出堆栈的方法有哪些? 我有一个这样的方式使用递归溢出堆栈
#include <iostream>
void func()
{
int arr[100500];
func();
}
int main()
{
func();
std :: cin.ignore(); std :: cin.get();
return 0;
}
但我不喜欢它。
在main()
你叫func()
然后调用func()
(本身),然后调用func()
(本身)等
每次调用一个函数,指针被压入堆栈。堆栈是有限的内存量,最终会填满,然后你得到一个stack overflow
。
由于您的程序将无休止地调用func()
堆栈将会快速填充。
还要注意,本地变量arr
也将被分配到堆栈上。这将更快地填满堆栈。
当递归太深时,可能导致堆栈溢出,因为函数本地变量和返回地址存储在堆栈中。在你的情况下,你有无限递归,也就是说,你没有一个条件来阻止func()调用自己,因此你正在溢出堆栈。
没有定义的限制,它取决于您运行递归的语言和体系结构。
不知道,谢谢! :) – m0skit0 2012-02-09 07:54:36
你可能想阅读这个问题的答案,http://stackoverflow.com/questions/2630054/does-c-limit-recursion-depth。 C++语言没有定义堆栈深度的限制。另一方面,您的操作系统将强制限制堆栈占用的空间量。 – aalpern 2012-02-09 07:59:09
@LuchianGrigore你在哪里找到这个定义的下限?我从来没有见过它,也没有听说过它,我无法在标准中找到它。 (当然,在标准中找东西并不总是微不足道的。) – 2012-02-09 08:23:37
由于无限递归,填充堆栈非常容易;
void func() { func(); }
会做得很好。任何函数调用都会将信息压入堆栈(至少是一个返回地址),所以如果在某个时刻它不停止调用它自己,它将用完堆栈。
我发现很难明白为什么你会不喜欢这样的功能,就像你所做的那样。它可以满足需要,而且速度很快。
但是,优化可能会导致编译器将函数变成无限循环,因为很容易发现它不起任何作用。
如果你想真正做什么事情的一个功能的演示,
int factorial(int n) { return n<= 0 ? 1 : factorial(n - 1) * n; }
就是一个很好的例子,给定一个适当大的值n,并没有编译器优化(也可能发现了尾巴的机会递归并将其转化为循环)。
如果做不到这一点,试试这个(阿克曼的功能,递归函数不是原始地递归,也不会受到在最后一行优化的一个例子。
unsigned int A(unsigned int m, unsigned int n)
{
if (m == 0) return n + 1;
if (n == 0) return A(m - 1, 1);
return A(m - 1, A(m, n - 1));
}
读者做练习:给定一个智能编译器,可以使用多少优化来最小化递归。
int arr [1005000000000000000000000000];' – 2012-02-09 07:45:26
int a [1 << 31]; //如果编译器允许 – loxxy 2012-02-09 07:48:04
@Andrew。你的问题?你说你不喜欢它,但是在对一个答案的评论中,你认为它不是 上班。 – stefaanv 2012-02-09 08:08:10