Die richtige Antwort lautet, dass diese Funktion nicht für alle Ganzzahlen beendet wird (insbesondere endet sie nicht bei -1). Ihr Freund hat Recht, wenn er angibt, dass dies Pseudocode ist und Pseudocode nicht bei einem Stapelüberlauf endet. Pseudocode ist formal nicht definiert, aber die Idee ist, dass es das tut, was auf dem Zinn steht. Wenn der Code nicht "Beenden mit einem Stapelüberlauffehler" sagt, liegt kein Stapelüberlauffehler vor.
Selbst wenn dies eine echte Programmiersprache wäre, wäre die richtige Antwort immer noch "nicht terminieren", es sei denn, die Verwendung eines Stacks ist Teil der Definition der Sprache. Die meisten Sprachen spezifizieren nicht das Verhalten von Programmen, die den Stapel überlaufen könnten, da es schwierig ist, genau zu wissen, wie viel Stapel ein Programm verwenden wird.
Wenn das Ausführen des Codes auf einem tatsächlichen Interpreter oder Compiler in vielen Sprachen einen Stapelüberlauf verursacht, ist dies eine Diskrepanz zwischen der formalen Semantik der Sprache und der Implementierung. Es ist allgemein bekannt, dass Implementierungen einer Sprache nur das tun, was auf einem konkreten Computer mit endlichem Speicher möglich ist. Wenn das Programm mit einem Stapelüberlauf abstürzt, sollten Sie einen größeren Computer kaufen, das System bei Bedarf neu kompilieren, um den gesamten Speicher zu unterstützen, und es erneut versuchen. Wenn das Programm nicht beendet wird, müssen Sie dies möglicherweise für immer tun.
Sogar die Tatsache, dass ein Programm den Stapel überläuft oder nicht überläuft, ist nicht genau definiert, da einige Optimierungen, wie die Optimierung von Tail Calls und das Merken , eine unendliche Kette von Funktionsaufrufen in einem konstant gebundenen Stapelraum ermöglichen können. Einige Sprachspezifikationen verlangen sogar, dass Implementierungen, wenn möglich, eine Tail-Call-Optimierung durchführen (dies ist in funktionalen Programmiersprachen üblich). Erweitert für diese Funktion f(-1)
auf f(f(-2))
; Der äußere Aufruf von f
ist ein Tail-Aufruf, sodass nichts auf den Stapel geschoben wird, sondern nur f(-2)
auf den Stapel verschoben -1
wird. Das Ergebnis ist, dass der Stapel wieder in dem Zustand ist, in dem er zu Beginn war. Somit bleibt bei der Tail-Call-Optimierung die f(-1)
Schleife für immer im Dauerspeicher.