2010-03-23 15 views
10

Warum segregiert das folgende Programm?Rekursive main() - warum segfault?

int main() { main(); } 

Auch wenn es eine Rekursion ist, das nicht am Ende und ist daher ungültig definitionsgemäß, ich sehe nicht, warum es Segfaults (gcc 4.4.3 und Klirren 1.5 (Stamm)).

+24

Es heißt ein "Stack-Überlauf" –

+0

@wic: Und soweit man sehen kann, ist es keine Pflanze, es war eine echte Frage. Viel Spaß! –

+0

@ T.J: Ja, das OP ist ein Genie und weiß es nicht einmal :) –

Antwort

26

Weil es jedes Mal, wenn es sich selbst aufruft, etwas Stapelspeicherplatz zuweist; Irgendwann werden der Stack-Speicherplatz und die Segfaults knapp. Ich bin ein bisschen überrascht, dass es mit einem segfault geht, obwohl; Ich hätte erwartet (Trommelwirbel) stack overflow!

+0

Diese Maschine hat 4 GB RAM und es segfaults in weniger als einer Sekunde. Ich glaube nicht, dass es nicht genug RAM hat. Meinst du, der Stack kann nur so klein sein, dass es so schnell passiert? – user299831

+10

@ user2999831 Der Stack ist normalerweise auf 1 Megabyte beschränkt. – sharptooth

+0

@ user299831: Es hat nichts damit zu tun, wie viel RAM Sie in Ihrem System haben. Für jeden Thread gibt es maximale Stapelgröße (1 MB in Visual Studio, kann geändert werden). Wenn Sie diese Größe überschreiten, erhalten Sie einen Stapelüberlauf. – Naveen

35

Sie erhalten eine stack overflow (!)

+2

Es ist erstaunlich, dass, wenn ich den Link zum ersten Mal klicke, ich sofort zum Überlauf stapeln! Nicht ein sehr tiefer Stack, denke ich ... – AnT

2

Es führt Überlauf zu stapeln, die als segfault auf Ihrem System diagnostiziert wird.

3

ist recurse ohne Basisfall, der einen Stapelüberlauf verursacht

10
int main() { main(); } 

einen Stapelüberlauf verursachen.

Aber

eine optimierte Version (nicht Debug-Modus) wie folgt aus:

int main() { 
    return main(); 
} 

die Rekursion in einem Schwanz-rekursive Aufruf, auch bekannt als eine Endlosschleife verwandeln!

+0

Eigentlich wird in diesem Beispiel auch gcc -O3 den Loop optimieren. –

+0

@Nick Wie sind die beiden verschieden? – Adil

+0

@Adil, es ist Compiler abhängig, aber es ist möglich, dass, wenn wir nicht explizit das Haupt "zurückgeben" der Compiler es nicht in eine Tail-Rekursion konvertieren. (Beispielfälle: 'if (1) {main();} return 0;' und 'if (1) {return main();} return 0;') –

1

Jeder Funktionsaufruf fügt Ganzzahlen im Stapel hinzu und diese Einträge werden beim Beenden der Funktion aus dem Stapel entfernt. Hier haben wir einen rekursiven Funktionsaufruf, der keine Ausgangsbedingung hat. Es wird also eine unendliche Anzahl von Funktionen nacheinander aufgerufen, und diese Funktion wird niemals beendet, und ihre gesamten Werte werden nie aus dem Stapel entfernt, was zu einem Stapelüberlauf führt.