2012-02-09 143 views
-2

使用递归溢出堆栈的方法有哪些? 我有一个这样的方式使用递归溢出堆栈

#include <iostream> 

void func() 
{ 
    int arr[100500]; 
    func(); 
} 

int main() 
{ 
    func(); 

    std :: cin.ignore(); std :: cin.get(); 

    return 0; 
} 

但我不喜欢它。

+0

int arr [1005000000000000000000000000];' – 2012-02-09 07:45:26

+0

int a [1 << 31]; //如果编译器允许 – loxxy 2012-02-09 07:48:04

+0

@Andrew。你的问题?你说你不喜欢它,但是在对一个答案的评论中,你认为它不是 上班。 – stefaanv 2012-02-09 08:08:10

回答

0

main()你叫func()然后调用func()(本身),然后调用func()(本身)等

每次调用一个函数,指针被压入堆栈。堆栈是有限的内存量,最终会填满,然后你得到一个stack overflow

由于您的程序将无休止地调用func()堆栈将会快速填充。

还要注意,本地变量arr也将被分配到堆栈上。这将更快地填满堆栈。

+0

我知道它:)但是,当我测试(在MSVC++ 2010)时,没有迹象表明堆栈已满... – Andrew 2012-02-09 07:52:15

+0

测试究竟是什么? – 2012-02-09 07:54:09

+0

我的第一篇文章中的代码。 – Andrew 2012-02-09 07:57:21

0

当递归太深时,可能导致堆栈溢出,因为函数本地变量和返回地址存储在堆栈中。在你的情况下,你有无限递归,也就是说,你没有一个条件来阻止func()调用自己,因此你正在溢出堆栈。

没有定义的限制,它取决于您运行递归的语言和体系结构。

+0

不知道,谢谢! :) – m0skit0 2012-02-09 07:54:36

+0

你可能想阅读这个问题的答案,http://stackoverflow.com/questions/2630054/does-c-limit-recursion-depth。 C++语言没有定义堆栈深度的限制。另一方面,您的操作系统将强制限制堆栈占用的空间量。 – aalpern 2012-02-09 07:59:09

+0

@LuchianGrigore你在哪里找到这个定义的下限?我从来没有见过它,也没有听说过它,我无法在标准中找到它。 (当然,在标准中找东西并不总是微不足道的。) – 2012-02-09 08:23:37

2

由于无限递归,填充堆栈非常容易;

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)); 
} 

读者做练习:给定一个智能编译器,可以使用多少优化来最小化递归。