2009-11-01 10 views

Répondre

14

Le cas typique qui n'implique pas la récursion infinie est la déclaration d'une variable automatique sur la pile qui est trop grande. Par exemple:

int foo() 
{ 
    int array[1000000]; 

} 
6
void function() 
{ 
function(); 
} 
+1

+1 propre et direct. C'est tout ce dont vous avez besoin pour faire sauter la pile. –

+1

Pouvons-nous le raccourcir? Oui nous pouvons! 'void _() {_();} ... c'est presque comme Perl;) – Thomas

+1

La différence est qu'en Perl, il est plus probable que vous allez souffler * votre * pile avant que Perl ne le fasse. – Rob

1

Cet exemple montre une récursivité incontrôlée. Finalement, la pile espacé alloué à ce processus sera complètement écrasé par des instances de bar et ret ...

int foo(int bar) 
{ 
    int ret = foo(42); 
    return ret; 
} 
3

continuer à essayer de revenir principale jusqu'à ce que la pile est épuisée?

int main(int argc, char **argv) 
{ 
    return main(argc, argv); 
} 
+3

Il n'est pas légal d'appeler main() en C++. – Tmdean

+0

Je sais qu'il ne formatera pas correctement, mais il n'y a pas d'avertissement avec '-Wall' même pour ce programme plus approprié: int main(int argc, char **argv) { if (argc == 0){return 0;} else {std::cout << argc << std::endl; return main(0, argv);} }

+0

Je veux dire qu'il est étrange que' g ​​++ 'ne donne aucun avertissement quand vous appelez main; vous avez en effet raison (d'après ce que j'ai vu) que la norme ne permet pas d'appeler 'main'. –

0

récursion infinie:

 
void infiniteFunction() 
{ 
    infiniteFunction(); 
} 

int main() 
{ 
    infiniteFunction(); 
    return 0; 
} 
5

est ici qui pourrait se produire dans la pratique:

int factorial(int x) { 
    return x == 0 ? 1 : x * factorial(x-1); 
} 

Cette pile déborde la pour x négative. Et, as Frank Krueger mentioned, également pour trop grand (mais alors int déborderait d'abord).

3

Comme pour modifier :-)

void ping() 
{ 
    pong(); 
} 

void pong() 
{ 
ping(); 
} 

Aussi, je crois que vous pouvez obtenir un débordement de pile si vous essayez d'allouer plus d'espace que la taille maximale de la pile de fil (1 Mo par défaut dans VS), donc quelque chose comme int a[100000]; devrait fournir l'exception.

+0

appelez-les ping et pong lol Nice one –

+0

ouais, un nom humoristique! –

2

Je ne peux pas croire que nous ayons omis le plus grand exemple de récurrence de tous les temps, factoriel!

#include <stdio.h> 

double fact(double n) { 
    if (n <= 0) return 1; 
    else return n * fact(n - 1); 
} 

int main() { 
    printf("fact(5) = %g\n", fact(5)); 
    printf("fact(10) = %g\n", fact(10)); 
    printf("fact(100) = %g\n", fact(100)); 
    printf("fact(1000) = %g\n", fact(1000)); 
    printf("fact(1000000) = %g\n", fact(1000000)); 
} 

Sur OS X 10.5.8 avec GCC 4.0.1:

$ gcc f.c -o f && ./f 
fact(5) = 120 
fact(10) = 3.6288e+06 
fact(100) = 9.33262e+157 
fact(1000) = inf 
Segmentation fault 

Malheureusement, OS X fait état d'une "Segmentation fault" au lieu d'un "débordement de pile". Dommage.

0

Vous pouvez également obtenir un débordement de pile si vous essayez de placer des objets volumineux sur la pile (valeur de référence).

1

Si vous voulez générer un programme explicitement non récurrent pour entraîner un débordement de pile par les appels de fonction:

#!/usr/bin/env python 
import sys 

print "void func" + sys.argv[1] + "() { }" 
for i in xrange(int(sys.argv[1])-1, -1, -1): 
    print "void func" + str(i) + "() { func" + str(i+1) + "(); }" 
print "int main() { func0(); return 0; }" 

Exemple de sortie:

$ python recursion.py 5 
void func5() { } 
void func4() { func5(); } 
void func3() { func4(); } 
void func2() { func3(); } 
void func1() { func2(); } 
void func0() { func1(); } 
int main() { func0(); return 0; } 

Exemple d'utilisation:

$ python recursion.py 250000 | g++ -x c++ - && ./a.out 

Au moins sur mon système, la pile d'appels s semble être 174602, donc vous aurez besoin de mettre l'argument à recursion.py pour être plus grand que cela; et il faut quelques minutes pour compiler et lier le programme.

3

exemple Compile temps:

template <int N> 
struct Factorial { 
    enum { value = N * Factorial<N - 1>::value }; 
}; 

// ... 
{ 
    int overflow = Factorial<10>::value; 
}