Rekursionslimit

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
raorao
User
Beiträge: 24
Registriert: Mittwoch 30. Dezember 2009, 15:35

Hoi mitenand!

Dass Rekursion mit Python eher vorsichtig zu geniessen ist habe ich an anderer Stelle bereits gefunden. Mir ist natürlich klar, dass folgender Code porblemlos mittels for oder while Schleife geschrieben werden könnte, es geht mir nur ums allgemeine Verständnis für Fälle, in denen die Rekursion weniger einfach zu umgehen ist und aber trotzdem ein hohes Rekursionslimit nötig ist. Trotzdem würde ich gerne begreifen, wieso folgender Code auf meinem Computer nach ca. 9600 Durchläufen einfach abbricht ohne Fehlermeldung!? Kann mir das jemand in einfachem Deutsch erklären. Wieso wird da kein Fehler geworfen?

Code: Alles auswählen

import sys
sys.setrecursionlimit(10000000)

def rec(c):
    c += 1
    if c % 100 == 0:
        print c
    rec(c)

rec(0)
Herzlichen Dank!
Darii
User
Beiträge: 1177
Registriert: Donnerstag 29. November 2007, 17:02

Du kriegst keine Warnung, weil das Rekursionslimit nur ein Schutzschild ist, das verhindert, dass du das reale(durch die C-Stackgröße bestimmte) Rekursionslimit tatsächlich überschreitest, damit der Python-Interpreter noch einen Ausnahme werfen kann.

Setzt du das Rekursionslimit hingegen auf irgendeinen viel zu hohen Wert, dann crasht der Interpreter im Zweifelsfall einfach ohne eine Fehlermeldung auszugeben.

Um das zu umgehen kannst du zum einen die Stackgröße heraufsetzen (im Beispiel das Maximum unter OSX)

Code: Alles auswählen

ulimit -s 65532
oder alternativ Stackless Python nehmen, das benutzt nicht den normalen C-Stack und crasht erst viel später.
Zuletzt geändert von Darii am Dienstag 4. Mai 2010, 14:48, insgesamt 2-mal geändert.
BlackJack

@raorao: Ich komme bis 15800 und das dürfte der gleiche Grund sein, warum folgendes C-Programm bei mir nur bis 261900 kommt (ohne Optimierungen übersetzt):

Code: Alles auswählen

#include <stdint.h>
#include <stdio.h>

void rec(uint32_t n)
{
    n += 1;
    if (n % 100 == 0) printf("%d\n", n);
    rec(n);
}

int main(void)
{
    rec(0);
    return 0;
}
Der C-Aufrufstack ist halt auch begrenzt. Bei mir kommt in beiden Fällen ein "segfault", also ein Abbruch weil das Programm auf Speicher zugreifen möchte, auf den es nicht zugreifen darf.
Benutzeravatar
Defnull
User
Beiträge: 778
Registriert: Donnerstag 18. Juni 2009, 22:09
Wohnort: Göttingen
Kontaktdaten:

raorao hat geschrieben:...für Fälle, in denen die Rekursion weniger einfach zu umgehen ist...
OT: Soweit ich weiß kann schon per Definition jedes rekursive Problem auch iterativ gelöst werden.
Bottle: Micro Web Framework + Development Blog
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

Defnull hat geschrieben:OT: Soweit ich weiß kann schon per Definition jedes rekursive Problem auch iterativ gelöst werden.
Er hat auch "weniger einfach" gesagt ;) Seinen eigenen Stack zu benutzen ist zwar problemlos möglich aber doch eher schwer verständlich.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Naja, da der gezeigte Quelltext ist Endrekursiv also könnte man mal schauen was der TCO-Dekorator bringt.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Antworten