2009-11-01 15 views

risposta

14

Il caso tipico che non prevede la ricorsione infinita sta dichiarando una variabile automatica nello stack troppo grande. Ad esempio:

int foo() 
{ 
    int array[1000000]; 

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

+1 pulito e diretto. Questo è tutto ciò di cui hai bisogno per saltare in aria. –

+1

Possiamo renderlo più breve? Sì possiamo! 'void _() {_();}' ... è quasi come Perl;) – Thomas

+1

La differenza è, in Perl land, è più probabile che tu faccia saltare * il tuo * stack prima di Perl. – Rob

1

Questo esempio mostra una ricorsione incontrollata. Alla fine, lo stack Spaced assegnato a questo processo sarà completamente sovrascritto da istanze di bar e ret ...

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

continuare a cercare di tornare principale fino a quando la pila si esaurisce?

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

Non è legale chiamare il principale() in C++. – Tmdean

+0

So che non verrà formattato correttamente, ma non ci sono avvisi con '-Wall' anche per questo programma più appropriato: int main(int argc, char **argv) { if (argc == 0){return 0;} else {std::cout << argc << std::endl; return main(0, argv);} }

+0

Voglio dire che è strano che' g ++ 'non dia alcun avvertimento quando si chiama main; sei effettivamente corretto (da quello che ho visto) che lo standard non consente di chiamare 'main'. –

0

ricorsione infinita:

 
void infiniteFunction() 
{ 
    infiniteFunction(); 
} 

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

Qui è uno che potrebbe accadere in pratica:

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

Questo overflow stack per negativo x. E, as Frank Krueger mentioned, anche per troppo grande x (ma poi int sarebbe troppo pieno prima).

3

Come per modificare :-)

void ping() 
{ 
    pong(); 
} 

void pong() 
{ 
ping(); 
} 

Inoltre, credo che si può ottenere overflow dello stack se si tenta di allocare più spazio alla dimensione massima dello stack di thread (1MB per impostazione predefinita in VS), in modo da qualcosa come int a[100000]; dovrebbe fornire l'eccezione.

+0

chiamarli ping e pong lol Nice one –

+0

sì, un nome divertente! –

2

Non posso credere che abbiamo lasciato il più grande esempio di ricorsione di tutti i tempi, fattoriale!

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

Su OS X 10.5.8 con 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 

Purtroppo, OS X segnala un "Segmentation fault" invece di un "overflow stack". Peccato.

0

È anche possibile ottenere uno stack in eccesso se si tenta di mettere oggetti di grandi dimensioni nello stack (in base al valore).

1

Se si desidera generare un programma esplicitamente non ricorsiva di provocare un overflow dello stack per funzione chiamate: uscita

#!/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; }" 

Esempio:

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

utilizzo Esempio:

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

Almeno sul mio sistema, lo stack di chiamate s sembra essere 174602, quindi sarà necessario impostare l'argomento su recursion.py per essere più grande di quello; e ci vogliono alcuni minuti per compilare e collegare il programma.

3

tempo di compilazione esempio:

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

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