Gibt es eine Möglichkeit, die verfügbare Stapelgröße vor dem rekursiven Aufruf zu überprüfen? (C #)

8

Für ein C # AI-Programm verwende ich einen rekursiven Aufruf, um den besten nächsten Zug zu finden (mit einem 30x30-Array, um den aktuellen Board-Zustand zu speichern). Für jeden Zug, den ich mache, möchte ich sehen, welche der möglichen Züge ich aus dem neuen Board-Zustand machen kann, ist am besten ... und so weiter, bis ich entweder eine "Spielende" -Position erreiche (keine weiteren Züge möglich) Zustand) oder ein Timer stoppt den Prozess und es werden keine weiteren rekursiven Aufrufe getätigt (und die "beste" bekannte Position wird zurückgegeben). Dies nur um zu erklären, warum ich Rekursion verwenden muss (es ist keine Tail-Rekursion) und ich kann keinen einzigen (globalen) Board-Zustand verwenden, sondern muss alle Board-Zustände aus dem aktuellen Zustand suchen.

(Manchmal) Ich erhalte eine System.StackOverflowException. Gibt es eine Möglichkeit, den verfügbaren Stapelspeicherplatz vor dem nächsten rekursiven Aufruf zu überprüfen? Dann könnte ich einfach den aktuellen Zustand als "beste bisher gefundene Position" zurückgeben und nicht den nächsten rekursiven Aufruf machen. I.e. Wenn der verfügbare Stapel zu klein wird, sollte er auch als Basisfall zählen.

Die andere Möglichkeit besteht natürlich darin, jeden rekursiven Aufruf in einen try..catch-Block zu setzen und die System.StackOverflowException zu behandeln, indem Sie sie als Basisfall verwenden?

    
Chavoux Luyt 09.09.2012, 15:54
quelle

4 Antworten

1

Wenn Sie diesen Pfad wirklich durchgehen möchten, können Sie % verwenden. co_de% Methode.

Wie andere bereits erwähnt haben, kann nicht ab% .NET von der .NET 2.0-Dokumentation abhören, aber aus der MSDN-Dokumentation wissen Sie, dass die vorherige Methode folgendes Verhalten aufweist:

  

Stellt sicher, dass der verbleibende Stapelspeicherplatz groß genug ist, um den Befehl auszuführen   durchschnittliche .NET Framework-Funktion.

Wenn der Stapel nach dieser Methode nicht groß genug ist, wird eine EnsureSufficientExecutionstack Ausnahme, die Sie fangen können .

    
João Angelo 09.09.2012, 16:03
quelle
2

Sie können eine Warteschlange + Schleife ( Queue<TNode> + while (queue.MoveNext()) ) anstelle der Rekursion verwenden und die Größe der Warteschlange begrenzen.

Oder Sie könnten offene Aufrufe für die Methode zählen und die Rekursion auf diese Weise begrenzen. (Zählen Sie Ein- und Ausgänge und geben Sie keine Rekursion ein, wenn Einträge - existieren & gt; maxOpenCalls).

    
Danny Varod 09.09.2012 16:00
quelle
2

Tatsächlich wird das System die Stapelgröße dynamisch erweitern, falls auf dem vorhandenen Stapel kein Platz mehr vorhanden ist. Selbst wenn Sie die Größe des Stapels testen könnten, wäre das nicht wirklich wichtig.

Ссылка Einzelheiten

  

Das System schreibt zusätzliche Seiten aus dem reservierten Stapelspeicher, wie sie benötigt werden, bis entweder der Stapel die reservierte Größe minus eine Seite erreicht (die als Schutzseite verwendet wird, um einen Stapelüberlauf zu verhindern) oder das System so wenig Arbeitsspeicher hat dass der Vorgang fehlschlägt ".

Was besagt, dass der Stapel vor der Rekursion eine Größe hat; und wenn die Rekursion einen Stapelüberlauf verursacht, hat der Stapel eine neue Größe, als das passiert ist.

Da Sie die StackOverflowException anstelle der terminalen Rekursion nicht abfangen können, können Sie die Tail-Rekursion verwenden. Der folgende Link bietet einige gute Details zur Umwandlung von Terminalrecession in Tail Recusion: Ссылка

    
Peter Ritchie 09.09.2012 15:56
quelle
1

Beginnend mit .NET 2 können Sie StackOverflowException NICHT abfangen

>

Die einzige Möglichkeit, zu bestimmen, wie viel von Ihrem Stack bereits verwendet wird, bedeutet, unsicheren Code zu verwenden, von dem ich dringend abraten sollte ... besser ein explizites Heap-basiertes Stack<T> zu verwenden.

    
Yahia 09.09.2012 16:01
quelle