En tant que programmeur, vous connaissez certainement l’erreur d’un débordement de pile due à une récursion évidente. Mais il existe certainement de nombreux moyens étranges et inhabituels pour que votre langue préférée crache cette erreur.
Objectifs:
- Doit provoquer un débordement de pile clairement visible sur la sortie d'erreur.
- Non autorisé à utiliser une récursivité évidente.
Exemples de programmes non valides:
// Invalid, direct obvious recursion.
methodA(){ methodA(); }
// Invalid, indirect, but obvious recursion.
methodA(){ methodB(); }
methodB(){ methodA(); }
Les moyens les plus créatifs sont les meilleurs car il s’agit d’un concours de popularité . Par exemple, évitez les réponses évidentes ennuyeuses comme celle-ci:
throw new StackOverflowError(); // Valid, but very boring and downvote-deserving.
Même si j'ai accepté une réponse maintenant, ajouter d'autres réponses est toujours correct :)
popularity-contest
stack
masterX244
la source
la source
Réponses:
Python
Cela entraînera l'échec immédiat de l'interprète:
Au lieu d'utiliser la récursivité, la pile est réduite afin qu'elle déborde immédiatement.
la source
Python
la source
C / Linux 32bit
Fonctionne en écrasant l'adresse de retour,
g
retourne donc au pointmain
avant d'appelerf
. Cela fonctionnera pour toute plate-forme où les adresses de retour sont sur la pile, mais peuvent nécessiter des ajustements.Bien sûr, écrire en dehors d'un tableau est un comportement indéfini , et vous n'avez aucune garantie que cela provoquera un débordement de pile au lieu de peindre votre moustache en bleu. Les détails des indicateurs de plate-forme, de compilateur et de compilation peuvent faire toute la différence.
la source
JavaScript / DOM
Si vous voulez tuer votre navigateur, essayez-le dans la console.
la source
with (document.body) { addEventListener('DOMSubtreeModified', function() { appendChild(firstChild); }, false); title = 'Kill me!'; } 15:43:43.642 TypeError: can't convert undefined to object
Java
J'ai vu quelque chose comme ça quelque part ici:
Edit: Trouvé à l'endroit où je l'ai vu: la réponse de Joe K au programme le plus court qui génère une erreur StackOverflow
Cela peut dérouter certains débutants en Java. Il cache simplement l'appel récursif.
val + this
devientval + this.toString()
parce queval
est une chaîne.Voir le courir ici: http://ideone.com/Z0sXiD
la source
new StringBuilder().append(val).append("").append(this).toString()
, et la dernière annexe appelle String.valueOf (...), qui à son tour appelle toString. Cela rend votre trace de pile un peu variée (trois méthodes sont présentées ici)."" + this.toString()
.+ "" +
pourrait tromper les gens, car cela semble inutile à première vue.String val;
etreturn val + this;
pourrait être légèrement sneakier""
construction de -String consiste à+ ""
C
Assez facile:
la source
ulimit -s unlimited
dans le shell résout ce problème sous linux)~0u
est un assez grand nombre en C.Dépassement de pile non récursif en C
Appel incompatibilité de convention.
Compiler avec
gcc -O0
.__cdecl
fonctions attendent l'appelant pour nettoyer la pile, et__stdcall
attend l'appelé à le faire, en appelant par le pointeur de fonction typecast, le nettoyage ne se fait jamais -main
pousse le paramètre sur la pile pour chaque appel , mais rien pops et , finalement , la la pile se remplit.la source
JavaScript
la source
+this
-il?+{toString:"".toLocaleString}
:-)J'étais frustré par le fait que java 7 et java 8 sont immunisés contre mon code diabolique dans ma réponse précédente . J'ai donc décidé qu'un patch pour cela était nécessaire.
Succès! J'ai fait
printStackTrace()
jeter unStackOverflowError
.printStackTrace()
est couramment utilisé pour le débogage et la journalisation et personne ne peut raisonnablement penser que cela pourrait être dangereux. Il n’est pas difficile de voir que ce code pourrait être utilisé pour créer de graves problèmes de sécurité:Certaines personnes peuvent penser qu'il s'agit d'une récursion évidente. Ce n'est pas. Le
EvilException
constructeur n'appelle pas lagetCause()
méthode pour que cette exception puisse être levée en toute sécurité après tout. L'appel de lagetCause()
méthode n'entraînera pas nonStackOverflowError
plus. La récursivité fait partie duprintStackTrace()
comportement normalement insoupçonné de JDK et de toute bibliothèque tierce utilisée pour le débogage et la journalisation utilisés pour inspecter l'exception. De plus, il est probable que le lieu où l'exception est levée est très éloigné de celui où il est traité.Quoi qu'il en soit, voici un code qui jette un
StackOverflowError
et ne contient aucun appel de méthode récursif après tout. LaStackOverflowError
passe en dehors de lamain
méthode, dans JDKUncaughtExceptionHandler
:la source
getCause()
méthode n'a pas pour résultatStackOverflowError
. Cela repose sur le fait qu'il existe un code du JDK qui appelle de manière récursive lagetCause()
méthode.getCause
simplement le corps,return this;
mais apparemment, Java est trop intelligent pour cela. Il remarque que c'est un "CIRCULAR REFERENCE
".StackOverflowError
paquet parce que le paquet OpenBSD 5.5 de jdk-1.7.0.21p2v0 a un bogue. Il ne jette pasStackOverflowError
. Il frappeSIGSEGV
et décharge le noyau.Assemblage Linux x86 NASM
Divulgacher:
la source
ret
C ++ au moment de la compilation
Il n'y a pas de récursivité ce fichier source, aucune des classes n'a elle-même une classe de base, même indirectement. (En C ++, dans une classe de modèle comme celle-ci,
S<1>
ilS<2>
s'agit de classes complètement distinctes.) L'erreur de segmentation est due au dépassement de capacité de la pile après la récursivité dans le compilateur.la source
template <typename T> auto foo(T t) -> decltype(foo(t)); decltype(foo(0)) x;
est un peu plus court.Bash (alerte de danger)
À proprement parler, cela n'entraînera pas directement un débordement de pile, mais générera ce que l'on pourrait appeler une " situation de génération persistante de pile-over-flow ": lorsque vous l'exécutez jusqu'à ce que votre disque soit plein, et que vous souhaitiez supprimer le désordre avec "rm -rf x ", celui-là est touché.
Cela ne se produit pas sur tous les systèmes, cependant. Certains sont plus robustes que d'autres.
Gros danger AVERTISSEMENT:
certains systèmes gèrent cela très mal et vous aurez peut-être du mal à nettoyer (parce que "rm -rf" lui-même rencontrera un problème de récusion). Vous devrez peut-être écrire un script similaire pour le nettoyage.
Mieux vaut essayer cela dans une machine à gratter si vous n’en êtes pas sûr.
PS: la même chose s'applique, bien sûr, si programmé ou fait dans un script batch.
PPS: il peut être intéressant d’obtenir un commentaire de votre part, sur le comportement de votre système particulier ...
la source
while cd x; do :; done; cd ..; while rmdir x; cd ..; done;
devrait s’occuper de ça.Java
Une belle de Java Puzzlers . Qu'est-ce que ça imprime?
En fait, il échoue avec une erreur StackOverflowError.
L'exception dans le constructeur est juste un hareng rouge. Voici ce que dit le livre à ce sujet:
la source
Latex
La pile d'entrée déborde parce qu'elle
\end
se développe de manière répétée dans une boucle infinie, comme expliqué ici .TeX échoue avec un
TeX capacity exceeded, sorry [input stack size=5000]
ou similaire.la source
BF
Peut-être que la pile débordera éventuellement, cela dépend de la longueur de la pile de l'interprète ...
la source
C #, au moment de la compilation
Le compilateur Microsoft C # peut détruire sa pile de différentes façons. chaque fois que vous voyez une erreur "expression est trop complexe à compiler" du compilateur C #, c'est certainement parce que la pile a fondu.
L'analyseur est une descente récursive, ainsi toute structure de langage suffisamment profondément imbriquée fera sauter la pile:
L'analyseur d'expression est assez intelligent pour éliminer les récursions sur le côté sur lequel on rentre généralement. Habituellement:
qui construit un arbre d'analyse extrêmement profond, ne fera pas sauter la pile. Mais si vous forcez la récursion à se produire de l'autre côté:
alors la pile peut être soufflée.
Ceux-ci ont la propriété inélégante que le programme est très grand. Il est également possible de faire entrer l'analyseur sémantique dans des récursions sans limite avec un petit programme car il n'est pas assez intelligent pour supprimer certains cycles impairs dans le système de types. (Roslyn pourrait améliorer cela.)
Je décris pourquoi cette analyse entre ici dans une récursion infinie:
http://blogs.msdn.com/b/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx
et pour de nombreux autres exemples intéressants, vous devriez lire cet article:
http://research.microsoft.com/en-us/um/people/akenn/generics/FOOL2007.pdf
la source
fatal error CS1647: An expression is too long or complex to compile near (code)
. La documentation de ce message d'erreur est ici , et c'est exactement ce que vous dites: "Il y a eu un débordement de pile dans le compilateur qui traite votre code."Sur Internet (utilisé par un milliard de personnes / jour)
Par exemple, sur le site Web de support de Dell (pas d'infraction, désolé Dell):
Si vous supprimez le TAG de support de l'URL, les redirections infinies sont effectuées . Dans l'URL suivante, ###### est un tag de support.
http://www.dell.com/support/drivers/uk/en/ukdhs1/ServiceTag/######?s=BSD&~ck=mn
Je crois que cela équivaut à un débordement de pile.
la source
/Errors/
URL supplémentaires à l'URL, puis s'arrête après la réception de HTTP 400 Bad Request. Mais ceci permet sans doute un débordement de pile supérieur à celui d’une redirection infinie.http://www.dell.com/support/drivers/uk/en/ukdhs1/ServiceTag/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/...
PHP
Un stackoverflow réalisé avec des éléments en boucle uniquement.
Explication (survolez pour voir le spoiler):
la source
while (1) { $a = array(&$a); }
ou quelque chose de similaire atteint la limite de mémoire…Java
J'ai fait exactement le contraire - un programme qui devrait évidemment générer une erreur de débordement de pile, mais ne le fait pas.
Astuce: le programme s'exécute dans le temps O (2 n ), et n est la taille de la pile (généralement 1024).
De Java Puzzlers # 45:
la source
finally
plutôt quecatch
, et le temps d'exécution est O (2 ^ n). Réponse mise à jour.C #
Premier post, alors s'il vous plaît, allez-y doucement sur moi.
Cela crée simplement une trace de pile, récupère le cadre supérieur (qui sera notre dernier appel
Main()
), récupère la méthode et l'appelle.la source
Java
printStackTrace()
entre une boucle infinie.printStackTrace()
jetteStackOverflowError
.Ce qui est fou, c'est que dans Java 5 et 6, cela ne provient pas du code utilisateur, cela se passe dans le code de JDK. Personne ne soupçonne raisonnablement qu'il
printStackTrace()
peut être dangereux d'exécuter.la source
InnerException
propriété est en lecture seule et est définie dans le constructeur, une réflexion est donc nécessaire.JavaScript: Mutation de fonction itérative non récursive
Il n'y a pas de récursion ici du tout.
f
sera de façon répétée avec de plus en plus d’arguments jusqu’à ce qu’elle puisse déborder de la pile en un seul appel de fonction. Laconsole.log
partie est optionnelle si vous voulez voir combien d'arguments sont nécessaires pour le faire. Cela garantit également que les moteurs intelligents JS ne l'optimiseront pas.Version Code-golf en CoffeeScript, 28 caractères:
la source
C # avec un échec épique
La façon dont cela échoue est épique, cela m'a complètement bouleversé:
Ce n'est qu'une image d'une série d'images étranges et apparemment infinies.
Cela doit être la chose la plus étrange jamais. Quelqu'un peut-il expliquer? Apparemment, le nombre croissant d'espaces utilisés pour l'indentation fait apparaître ces blocs blancs. Cela se produit sur une entreprise Win7 Enterprise x64 avec .NET 4.5.
Je n'en ai pas encore vu la fin. Si vous remplacez
System.Console.Out
parSystem.IO.Stream.Null
, il mourra assez vite.L'explication est assez simple. Je crée une classe qui n'a qu'une seule propriété et renvoie toujours une nouvelle instance de son type contenant. C'est donc une hiérarchie d'objet infiniment profonde. Maintenant, nous avons besoin de quelque chose qui essaie de lire cela. C'est là que j'utilise le
XmlSerializer
, ce qui ne fait que cela. Et apparemment, il utilise la récursivité.la source
frapper
Alors que beaucoup pourraient reconnaître que la récursion est évidente , elle semble jolie. Non?
Lors de l'exécution, vous êtes assuré de voir:
la source
_(){_|_;};_
{
syntaxe pour être correct?):(){:|:;}:
Haskell
(triste mais vrai jusqu'au moins
ghc-7.6
, bien qu'avecO1
ou plus cela optimisera le problème)la source
sum
est implémenté en termes defoldl
, ce qui utilise des appels de queue, mais parce qu’il n’évalue pas l’accumulateur, il ne produit strictement qu’une pile de thunks de la taille de la liste originale. Le problème disparaît lors du passage àfoldl' (+)
, cela évalue strictement et renvoie donc un WHN dans son appel final. Ou, comme je l'ai dit, si vous activez les optimisations de GHC!Petite conversation
Cela crée une nouvelle méthode à la volée, qui
crée une nouvelle méthode à la volée, qui
crée une nouvelle méthode à la volée, qui
...
...
...
puis y est transférée.
Un peu de piquant supplémentaire provient de la contrainte de mémoire de pile ET de mémoire de pile en même temps, en créant à la fois un nom de méthode de plus en plus long et un nombre énorme en tant que destinataire, au moment où nous tombons dans le trou ... (mais la récursion nous frappe en premier )
compiler en entier:
puis sautez, en évaluant
"2 downTheRabbitHole"
...... au bout d'un moment, vous vous retrouverez dans un débogueur, affichant une exception RecursionException.
Ensuite, vous devez nettoyer tout le désordre (SmallInteger et LargeInteger ont maintenant beaucoup de code du pays des merveilles):
ou bien passez quelque temps dans le navigateur, supprimant le pays des merveilles d'Alice.
Voici quelques-uns de la tête de la trace:
PS: le "withoutUpdatingChangesFile:" a été ajouté pour éviter de devoir nettoyer le fichier journal des modifications persistant de Smalltalk.
PPS: merci pour le défi: penser à quelque chose de nouveau et d'innovant était amusant!
PPPS: J'aime noter que certains dialectes / versions Smalltalk copient les trames de pile débordantes dans le tas - de sorte que celles-ci risquent de se trouver dans une situation de mémoire insuffisante.
la source
C #
Vraiment gros
struct
, pas de récursivité, C # pur, pas de code dangereux.comme un kicker, il bloque les fenêtres de débogage en indiquant que
{Cannot evaluate expression because the current thread is in a stack overflow state.}
Et la version générique (merci pour la suggestion NPSF3000)
la source
C #
Mauvaise implémentation de l'
==
opérateur de remplacement :On pourrait dire qu’il est évident que l’
operator==
appel se fait de lui-même en utilisant l’==
opérateur, mais vous ne pensez généralement pas de cette façon==
, il est donc facile de tomber dans ce piège.la source
Début de réponse en utilisant SnakeYAML
Edit: non-golfé
Il appartient au lecteur de savoir comment cela fonctionne: P (astuce: stackoverflow.com)
À propos: la récursivité est faite dynamiquement par SnakeYAML (vous remarquerez si vous savez comment il détecte les champs qu'il sérialise et regarde ensuite dans
Point
le code source)Edit: racontant comment ça marche:
SnakeYAML recherche une paire de méthodes
getXXX
etsetXXX
porte le même nomXXX
et le type de retour du getter est identique au paramètre de setter; et étonnamment laPoint
classe aPoint getLocation()
etvoid setLocation(Point P)
qui se retourne; SnakeYAML ne le remarque pas et revient sur cette bizarrerie et StackOverflows. Découvert celui-là en travaillant avec eux à l'intérieur d'unHashMap
et en demandant à stackoverflow.com dessus.la source
C #
getter de propriété implémenté à tort
la source
static void Main() { Main(); }
Main()
accidentellement. Mais il est assez simple d'écrire accidentellement une propriété récursive, puis de se laisser confondre par le débordement de pile.