Como programador, ciertamente conoce el error de un desbordamiento de pila debido a una recurrencia obvia. Pero ciertamente hay muchas formas extrañas e inusuales de hacer que su idioma favorito escupe ese error.
Objetivos:
- Debe provocar un desbordamiento de pila que sea claramente visible en la salida de error.
- No se permite usar una recurrencia obvia.
Ejemplos de programas inválidos:
// Invalid, direct obvious recursion.
methodA(){ methodA(); }
// Invalid, indirect, but obvious recursion.
methodA(){ methodB(); }
methodB(){ methodA(); }
Las formas más creativas son las mejores, ya que este es un concurso de popularidad . Es decir, evite respuestas obvias aburridas como esta:
throw new StackOverflowError(); // Valid, but very boring and downvote-deserving.
Aunque acepté una respuesta ahora, agregar más respuestas todavía está bien :)
popularity-contest
stack
masterX244
fuente
fuente
Respuestas:
Pitón
Esto hará que el intérprete falle inmediatamente:
En lugar de usar la recursividad, simplemente reduce la pila para que se desborde inmediatamente.
fuente
Pitón
fuente
C / Linux 32bit
Funciona sobrescribiendo la dirección de retorno, por lo que
g
vuelve al puntomain
antes de llamarf
. Funcionará para cualquier plataforma donde las direcciones de retorno estén en la pila, pero puede requerir ajustes.Por supuesto, escribir fuera de una matriz es un comportamiento indefinido , y no tiene garantía de que cause un desbordamiento de la pila en lugar de, por ejemplo, pintar el bigote de azul. Los detalles de la plataforma, el compilador y los indicadores de compilación pueden marcar una gran diferencia.
fuente
JavaScript / DOM
Si quieres matar tu navegador, prueba eso en la consola.
fuente
with (document.body) { addEventListener('DOMSubtreeModified', function() { appendChild(firstChild); }, false); title = 'Kill me!'; } 15:43:43.642 TypeError: can't convert undefined to object
Java
Vi algo como esto en algún lugar por aquí:
Editar: Encontrado donde lo vi: la respuesta de Joe K al programa más corto que arroja StackOverflow Error
Eso puede confundir a algunos principiantes de Java. Simplemente oculta la llamada recursiva.
val + this
se convierte enval + this.toString()
porqueval
es una cadena.Véalo correr aquí: http://ideone.com/Z0sXiD
fuente
new StringBuilder().append(val).append("").append(this).toString()
, y el último anexo llama a String.valueOf (...), que a su vez llama a String. Esto hace que el seguimiento de su pila sea un poco variado (tres métodos allí)."" + this.toString()
.+ "" +
podría alertar a la gente, ya que parece inútil a primera vista.String val;
yreturn val + this;
podría ser ligeramente más astuto""
construcción de -String es con el+ ""
C
Muy fácil:
fuente
ulimit -s unlimited
en el shell resuelve esto en Linux)~0u
es un número bastante grande en C.Desbordamiento de pila no recursivo en C
La convención de llamada no coincide.
Compilar con
gcc -O0
.__cdecl
las funciones esperan que la persona que llama limpie la pila, y__stdcall
espera que la persona que llama lo haga, por lo que al llamar a través del puntero de la función de conversión de texto, la limpieza nunca se realiza:main
empuja el parámetro a la pila para cada llamada, pero nada aparece y finalmente la pila se llenafuente
JavaScript
fuente
+this
hacer?+{toString:"".toLocaleString}
:-)Estaba frustrado por el hecho de que Java 7 y Java 8 son inmunes a mi código maligno en mi respuesta anterior . Entonces decidí que era necesario un parche para eso.
¡Éxito! Hice
printStackTrace()
tirar aStackOverflowError
.printStackTrace()
se usa comúnmente para depurar y registrar y nadie sospecha razonablemente que podría ser peligroso. No es difícil ver que se puede abusar de este código para crear algunos problemas de seguridad graves:Algunas personas pueden pensar que esta es una recurrencia obvia. No lo es. El
EvilException
constructor no llama algetCause()
método, por lo que, después de todo, esa excepción se puede lanzar de manera segura. Llamar algetCause()
método no dará como resultadoStackOverflowError
tampoco. La recursión está dentro delprintStackTrace()
comportamiento normalmente insospechado de JDK y de cualquier biblioteca de terceros para la depuración y el registro que se utilizan para inspeccionar la excepción. Además, es probable que el lugar donde se produce la excepción esté muy lejos del lugar donde se maneja.De todos modos, aquí hay un código que arroja un
StackOverflowError
y no contiene llamadas a métodos recursivos después de todo. Lo queStackOverflowError
ocurre fuera delmain
método, en JDK'sUncaughtExceptionHandler
:fuente
getCause()
método no da como resultadoStackOverflowError
. Se basa en el hecho de que hay un código de JDK que llama recursivamente algetCause()
método.getCause
soloreturn this;
pero aparentemente Java es demasiado inteligente para eso. Se da cuenta de que es un "CIRCULAR REFERENCE
".StackOverflowError
porque el paquete OpenBSD 5.5 de jdk-1.7.0.21p2v0 tiene un error. No tiraStackOverflowError
. GolpeaSIGSEGV
y descarga el núcleo.Ensamblaje NASM Linux x86
Revelación:
fuente
ret
C ++ en tiempo de compilación
No hay recurrencia en este archivo fuente, ninguna de las clases se tiene como clase base, ni siquiera indirectamente. (En C ++, en una clase de plantilla como esta,
S<1>
yS<2>
son clases completamente distintas.) El error de segmentación se debe al desbordamiento de la pila después de la recursión en el compilador.fuente
template <typename T> auto foo(T t) -> decltype(foo(t)); decltype(foo(0)) x;
Es un poco más corto.Bash (alerta de peligro)
Estrictamente hablando, eso no apilará directamente el desbordamiento, sino que generará lo que se puede etiquetar como " una situación persistente de generación de apilamiento por flujo ": cuando ejecuta esto hasta que su disco esté lleno y desea eliminar el desorden con "rm -rf x ", ese es golpeado.
Sin embargo, no sucede en todos los sistemas. Algunos son más robustos que otros.
Gran peligro ADVERTENCIA:
algunos sistemas manejan esto muy mal y es posible que tenga dificultades para limpiar (porque "rm -rf" en sí mismo se encontrará con un problema de recusión). Puede que tenga que escribir un script similar para la limpieza.
Mejor intente esto en una VM virtual si no está seguro.
PD: lo mismo se aplica, por supuesto, si se programa o se realiza en un script por lotes.
PPS: puede ser interesante recibir un comentario de usted, cómo se comporta su sistema particular ...
fuente
while cd x; do :; done; cd ..; while rmdir x; cd ..; done;
debería encargarse de esto.Java
Una buena de Java Puzzlers . ¿Qué imprime?
Realmente falla con un StackOverflowError.
La excepción en el constructor es solo un arenque rojo. Esto es lo que el libro tiene que decir al respecto:
fuente
Látex
La pila de entrada se desborda porque
\end
se expande repetidamente en un bucle infinito, como se explica aquí .TeX falla con una
TeX capacity exceeded, sorry [input stack size=5000]
o similar.fuente
BF
Eventualmente desbordará la pila, solo depende de cuánto tiempo el intérprete hace la pila ...
fuente
C #, en tiempo de compilación
Hay varias formas de hacer que el compilador de Microsoft C # explote su pila; cada vez que vea un error de "expresión es demasiado complejo para compilar" desde el compilador de C #, es casi seguro que la pila ha explotado.
El analizador es un descenso recursivo, por lo que cualquier estructura de lenguaje suficientemente anidada volará la pila:
El analizador de expresiones es bastante inteligente para eliminar las recursiones en el lado que comúnmente se recurre. Generalmente:
que construye un árbol de análisis enormemente profundo, no volará la pila. Pero si obligas a que ocurra la recursión en el otro lado:
entonces la pila se puede volar.
Estos tienen la propiedad poco elegante de que el programa es muy grande. También es posible hacer que el analizador semántico entre recurrencias ilimitadas con un pequeño programa porque no es lo suficientemente inteligente como para eliminar ciertos ciclos extraños en el sistema de tipos. (Roslyn podría mejorar esto).
Describo por qué este análisis entra en una recursión infinita aquí:
http://blogs.msdn.com/b/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx
y para muchos más ejemplos interesantes deberías leer este artículo:
http://research.microsoft.com/en-us/um/people/akenn/generics/FOOL2007.pdf
fuente
fatal error CS1647: An expression is too long or complex to compile near (code)
. La documentación para este mensaje de error está aquí , y es exactamente como usted dice: "Hubo un desbordamiento de pila en el compilador que procesaba su código".En Internet (utilizado por miles de millones de personas / día)
Por ejemplo, en el sitio web de asistencia de Dell (sin ofender, lo siento, Dell):
Si elimina el TAG de soporte de la URL, se redirige infinitamente . En la siguiente URL, ###### es cualquier TAG de soporte.
http://www.dell.com/support/drivers/uk/en/ukdhs1/ServiceTag/######?s=BSD&~ck=mn
Creo que es equivalente a un desbordamiento de pila.
fuente
/Errors/
a la URL y luego se detiene después de recibir HTTP 400 Bad Request. Pero esto podría ser un mejor desbordamiento de pila que una redirección infinita.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 hecho solo con elementos de bucle.
Explicación (pase el cursor para ver el spoiler):
fuente
while (1) { $a = array(&$a); }
o algo similar simplemente golpea el límite de memoria ...Java
Hice exactamente lo contrario: un programa que obviamente debería arrojar un error de desbordamiento de pila, pero no lo hace.
Sugerencia: el programa se ejecuta en tiempo O (2 n ), yn es el tamaño de la pila (generalmente 1024).
De Java Puzzlers # 45:
fuente
finally
lugar decatch
, y el tiempo de ejecución es O (2 ^ n). Respuesta actualizadaC#
Primera publicación, así que por favor ve con calma
Esto simplemente crea un seguimiento de la pila, toma el marco superior (que será nuestra última llamada
Main()
), obtiene el método y lo invoca.fuente
Java
printStackTrace()
ingresa un bucle infinito.printStackTrace()
tiraStackOverflowError
.Lo loco es que en Java 5 y 6, no proviene del código de usuario, sucede en el código de JDK. Nadie sospecha razonablemente que
printStackTrace()
pueda ser peligroso ejecutar.fuente
InnerException
propiedad es de solo lectura y se establece en el constructor, por lo que es necesario reflexionar para causar esto.JavaScript: mutación de función iterativa no recursiva
No hay recursividad aquí en absoluto.
f
se repetirá repetidamente con más y más argumentos hasta que pueda desbordar la pila en una sola llamada de función. Laconsole.log
parte es opcional en caso de que desee ver cuántos argumentos se necesitan para hacerlo. También asegura que los motores JS inteligentes no optimicen esto.Versión de código de golf en CoffeeScript, 28 caracteres:
fuente
C # con un fracaso épico
La forma en que falla es épica, me dejó alucinado por completo:
Es solo un fotograma de una serie de imágenes extrañas aparentemente infinitas.
Esto tiene que ser lo más raro que haya existido. ¿Alguien puede explicar? Aparentemente, la cantidad cada vez mayor de espacios utilizados para la sangría hace que aparezcan esos bloques blancos. Sucede en un Win7 Enterprise x64 con .NET 4.5.
Aún no he visto el final. Si reemplaza
System.Console.Out
conSystem.IO.Stream.Null
, muere bastante rápido.La explicación es bastante simple. Hago una clase que tiene una sola propiedad, y siempre devuelve una nueva instancia de su tipo que contiene. Entonces es una jerarquía de objetos infinitamente profunda. Ahora necesitamos algo que intente leerlo. Ahí es donde uso el
XmlSerializer
, que hace exactamente eso. Y aparentemente, usa la recursividad.fuente
golpetazo
Si bien muchos podrían reconocer que la recursión es obvia , pero parece bonita. ¿No?
Tras la ejecución, tiene la garantía de ver:
fuente
_(){_|_;};_
{
que sea sintácticamente correcto?):(){:|:;}:
Haskell
(triste pero cierto hasta al menos
ghc-7.6
, aunque conO1
o más optimizará el problema)fuente
sum
se implementa en términos defoldl
, que usa llamadas de cola, pero debido a que no evalúa estrictamente el acumulador, simplemente produce una pila de thunks tan grandes como la lista original. El problema desaparece al cambiar afoldl' (+)
, que evalúa estrictamente y, por lo tanto, devuelve un WHN en su cola. O, como dije, ¡si activa las optimizaciones de GHC!Charla
Esto crea un nuevo método sobre la marcha, que
crea un nuevo método sobre la marcha, que
crea un nuevo método sobre la marcha, que
...
...
..
y luego se transfiere a él.
Una pequeña especia extra proviene de estresar la memoria de la pila Y la memoria del montón al mismo tiempo, al crear un nombre de método más largo y más largo, y un gran número como receptor, a medida que caemos por el agujero ... (pero la recursión nos golpea primero )
compilar en entero:
luego salta, evaluando
"2 downTheRabbitHole"
...... después de un tiempo, terminarás en un depurador, mostrando una RecursionException.
Luego tienes que limpiar todo el desorden (tanto SmallInteger como LargeInteger ahora tienen mucho código de país de las maravillas):
o de lo contrario pasar algún tiempo en el navegador, eliminando el país de las maravillas de Alice
Aquí hay algunos de la cabeza del rastro:
PD: se agregó el "withoutUpdatingChangesFile:" para evitar tener que limpiar el archivo de registro de cambios persistente de Smalltalk después.
PPS: gracias por el desafío: ¡pensar en algo nuevo e innovador fue divertido!
PPPS: Me gustaría señalar que algunos dialectos / versiones de Smalltalk copian los marcos de pila desbordados en el montón, por lo que en su lugar pueden quedar sin memoria.
fuente
C#
Realmente grande
struct
, sin recursividad, C # puro, código no inseguro.como pateador, bloquea las ventanas de depuración indicando que
{Cannot evaluate expression because the current thread is in a stack overflow state.}
Y la versión genérica (gracias por la sugerencia NPSF3000)
fuente
C#
Implementación defectuosa del
==
operador anulado :Se podría decir que es obvio que se
operator==
llama a sí mismo utilizando el==
operador, pero generalmente no piensas de esa manera==
, por lo que es fácil caer en esa trampa.fuente
Iniciando respuesta usando SnakeYAML
Editar: sin golf
Depende del lector descubrir cómo funciona: P (consejo: stackoverflow.com)
Por cierto: SnakeYAML crea dinámicamente la recursividad (notará si sabe cómo detecta los campos que serializa y luego mira en
Point
el código fuente)Editar: diciendo cómo funciona ese:
SnakeYAML busca un par de
getXXX
ysetXXX
mthod con el mismo nombreXXX
y el tipo de retorno del getter es el mismo que el parámetro de setter; y sorprendentemente laPoint
clase tiene unPoint getLocation()
yvoid setLocation(Point P)
que regresa a sí mismo; SnakeYAML no lo nota y recurre a ese capricho y StackOverflows. Descubrí eso cuando trabajaste con ellos dentro deHashMap
y preguntando en stackoverflow.com sobre él.fuente
C#
getter de propiedad implementado incorrectamente
fuente
static void Main() { Main(); }
Main()
accidentalmente. Pero es bastante simple escribir una propiedad recursiva accidentalmente y luego confundirse con el desbordamiento de la pila.