Programa más corto que asigna memoria continuamente

49

Escriba un programa que se ejecute para siempre y asigne más y más memoria en el montón cuanto más tiempo se ejecute, al menos hasta que alcance el límite del sistema operativo en la cantidad de memoria que se puede asignar.

Muchos núcleos en realidad no reservarán la memoria que asigne hasta que la use para algo, por lo que si su programa está en C o en algún otro lenguaje de bajo nivel, deberá asegurarse de escribir algo en cada página. Si está utilizando un lenguaje interpretado, probablemente no tendrá que preocuparse por esto.

El código más corto gana.

tbodt
fuente
13
¿Es un desbordamiento de pila una solución válida? ¿La memoria tiene que ser filtrada o simplemente asignada?
Wheat Wizard
1
@WheatWizard La memoria no tiene que perderse, pero debe asignarse más rápido de lo que se desasigna.
tbodt
2
La única vez que quiero que mi programa consuma memoria infinita, no puedo hacerlo. (reduce conj [] (range))(Clojure) llega a 737mb, luego deja de crecer. No sé cómo no está subiendo continuamente. "Piensa" que quiero imprimir la lista completa al final, por lo que no debería tirar nada. Muy frustrante.
Carcigenicate
14
Nota personal: guarde el código antes de probar. Introducir mem-leaks podría bloquear IDE ...
steenbergh 02 de
1
Creo que debería agregar otro desafío de golf, similar pero separado de este, que requiere que el programa consuma memoria más rápido que una función lineal del tiempo. Para el desafío actual , hacer un ciclo para siempre y asignar un solo byte debería estar bien. Para su nuevo desafío, eso sería insuficiente, pero estaría bien hacer un bucle para siempre y duplicar la cantidad de memoria utilizada cada vez.
BenGoldberg

Respuestas:

46

Funge-98 ( cfunge), 1 byte

9

Hubiera publicado esto antes, pero decidí probarlo y me llevó un tiempo volver a poner mi computadora en un estado utilizable. cfungealmacena la pila Funge en el montón del sistema operativo (que es fácilmente verificable ejecutando el programa con un pequeño límite de memoria, ¡algo que debería haber hecho antes!), por lo que una pila que crece infinitamente (como con este programa, que simplemente empuja 9repetidamente; Los programas de Funge (desde el final de una línea hasta el inicio de forma predeterminada) asignarán memoria para siempre. Es probable que este programa también funcione en algunas implementaciones de Befunge-93.

Más interesante:

"NULL #(4

Esta fue mi primera idea, y es una asignación infinita que no depende de la pila Funge (aunque también explota la pila Funge). Para comenzar, el "comando empuja una copia del resto del programa a la pila (es una cadena, y el programa se ajusta, por lo que la comilla cerrada también sirve como comilla abierta). Luego, el Nreflejo (no tiene significado por defecto), lo que hace que el programa se ejecute al revés. Se "ejecuta nuevamente y empuja el programa a la pila, al revés esta vez, con la Nparte superior de la pila, luego el programa se ajusta, cargando una biblioteca con un nombre de 4 letras ( 4(; la NULLbiblioteca es parte de cfungeLa biblioteca estándar). NULLdefine todas las letras mayúsculas para reflejar, por lo que Lrefleja, el#omite la carga de la biblioteca en el camino de regreso, 4empuja basura que no nos importa a la pila y todo el programa se repite desde el principio. Dado que cargar una biblioteca varias veces tiene un efecto y requiere que la lista de comandos de la biblioteca se almacene una vez para cada copia de la biblioteca (esto está implícito en la semántica de Funge-98), pierde memoria a través del almacenamiento no apilado (que es un método alternativo para definir "montón", relativo al lenguaje en lugar del sistema operativo).


fuente
2
Solo voy a aceptar esto ...
tbodt
¿Es necesario que el número sea 9? ¿Funcionaría también si fuera 5?
tbodt
Cualquier cosa que empuje a la pila funciona (excepto posiblemente 0; es posible que la implementación de Funge o el sistema operativo puedan encontrar una manera de optimizar eso, dado que la memoria en cuestión ya está llena de ceros). Acabo de elegir 9arbitrariamente.
22
Inaceptable porque quiero que mi reputación siga siendo 666.
tbodt
77
@tbodt No es una razón real para no aceptar. Si lo desea, haré -1 su pregunta. Luego, cuando acepte, todavía tendrá 703 (tenga en cuenta que ahora tiene 703, no 666).
NoOneIsHere
30

Brainfuck, 5 bytes

+[>+]

Esto requiere un intérprete que no tenga límite en la longitud de la cinta.

vsz
fuente
2
Estoy bastante seguro de que es + [> +] o de lo contrario simplemente se detendría en la primera iteración. ;)
Pâris Douady
Tienes razón, perdón por el error tipográfico.
vsz
40
Uno de los raros momentos en que una solución de brainfuck es competitiva ...
FlipTack
@ Flp.Tkc Pero aún así pierde. Tal vez gane algún día ...
NoOneIsHere
66
@SeeOneRhino: Ya ganó una vez, superando todos los idiomas de golf> codegolf.stackexchange.com/questions/8915/…
vsz
22

Bash + coreutils, 5

o

Rubí, 5

`yes`

yesproduce salida sin fin. Poner yesen backticks le dice al shell que capture toda la salida y luego ejecute esa salida como un comando. Bash continuará asignando memoria para esta cadena interminable hasta que se agote el montón. Por supuesto, el resultado resultante terminaría siendo un comando no válido, pero deberíamos quedarnos sin memoria antes de que eso suceda.

Gracias a @GB por señalar que también es un políglota en rubí.

Trauma digital
fuente
77
Estaba a punto de escribir lo mismo y llamarlo un programa Ruby.
GB
1
y perl, creo.
Abligh
18

Python, 16 bytes

Sigue anidando ahasta que se alcanza un error:

a=0
while 1:a=a,

Las primeras iteraciones (como tuplas) se ven así:

0
(0,)
((0,),)
(((0,),),)

y así sucesivamente y así sucesivamente.

FlipTack
fuente
18

> <> (Pez), 1 byte

0

Pruébalo aquí!

0 en realidad se puede sustituir por cualquier número hexadecimal 1-f.

Explicación

0in> <> simplemente crea una caja de códigos 1x1 para que los peces naden. Constantemente agrega una 0a la pila, nada hacia la derecha, lo que hace un bucle hacia atrás y la 0agrega nuevamente a la pila. Esto continuará por siempre.

Redstarcoder
fuente
2
Ahora me pregunto en cuántos otros lenguajes bidimensionales funciona. La mayoría de ellos están basados ​​en la pila, después de todo.
1
Casi funciona en Cubix , pero requiere un carácter inicial .(o cualquier carácter que no sea un espacio en blanco) para moverlo 0a la línea de ejecución.
ETHproductions
1
Funciona en Ouroboros , pero no de la misma manera: el intérprete intenta leer 0000000...como un único entero literal, y la cadena que construye es lo que sigue teniendo más memoria. Un programa que funciona de la misma manera que este sería a(empuja 10 infinitamente).
DLosc
12

Java 101 bytes

class A{public void finalize(){new A();new A();}public static void main(String[]a){for(new A();;);}}

Capturando el programa principal en un bucle sin fin después de crear y tirar un objeto. La recolección de basura hace el trabajo de fugas al crear 2 objetos por cada uno eliminado

masterX244
fuente
bueno, me siento un poco tonto por no ir con lo obvio ahora, jaja. Me atrevería a decir que esto es más elegante que el mío
Poke
1
sí, su código me recordó a ese hecho con el finalize () @poke
masterX244
Creo que podría
acortarlo
solo funciona hasta java6 y solo obtuve versiones superiores
masterX244
2
jaja usando el recolector de basura para causar una fuga! gran idea :)
Mark K Cowan
12

Perl, 12 bytes

{$"x=9;redo}

En perl, el xoperador, con una cadena a la izquierda y un número a la derecha, produce una cadena repetida. Entonces "abc" x 3evalúa a "abcabcabc".

El x=operador muta el argumento izquierdo, reemplazando el contenido de la variable a su izquierda con el resultado de repetir su contenido tantas veces como lo indique su lado derecho.

Perl tiene varias variables incorporadas con nombres extraños, una de las cuales es $", cuyo valor inicial es un espacio único.

El redooperador salta al comienzo del cerramiento {}.

La primera vez que el x=se realiza el operador, cambia el valor de $"partir " ""a " ", que es de 9 espacios.

La segunda vez que el x=operador termina, cambia el valor de $"a " ", que es 81 espacios.

La tercera vez, se $"convierte en una cadena de espacios de 729 bytes de longitud.

Creo que puedes ver por donde está yendo :).

BenGoldberg
fuente
¡Me ganaste! Y el tuyo es tres bytes más corto.
Gabriel Benamy
1
Era solo una cuestión de buscar en este sitio web el bucle más pequeño :). Además, inicialmente tenía $_.=7en mi bucle, pero me di cuenta de que si podía usarlo, x=se quedaría sin memoria mucho más rápido, y luego corrí perldoc perlvarpara elegir algo adecuado.
BenGoldberg
{$^O++;redo}es un byte más corto cuando ^Oes un solo chr(15)byte. Aunque desperdiciará memoria a una velocidad MUCHO más lenta, se requieren 1000000000 iteraciones en Windows para desperdiciar un byte. Funcionará en cualquier sistema operativo que tenga su nombre comenzando en letra latina.
Oleg V. Volkov
11

sed, 5 bytes

Golfed

H;G;D

Uso (cualquier entrada servirá)

sed 'H;G;D' <<<""

Explicado

#Append a newline to the contents of the hold space, 
#and then append the contents of the pattern space to that of the hold space.
H

#Append a newline to the contents of the pattern space, 
#and then append the contents of the hold space to that of the pattern space. 
G

#Delete text in the pattern space up to the first newline, 
#and restart cycle with the resultant pattern space.
D

Captura de pantalla

ingrese la descripción de la imagen aquí

¡Pruébelo en línea!

zepelín
fuente
2
Estrictamente hablando, esto es GNU sed (el punto y coma no es sed estándar) pero una nueva línea funcionaría tan bien como el punto y coma de todos modos.
R ..
10

Haskell, 23 19 bytes

main=print$sum[0..]

Imprime la suma de una lista infinita

Angs
fuente
Esta es una buena manera de hacer cumplir la evaluación, y también es muy compacta. +1
Esolanging Fruit
un compilador podría ejecutar esto en la memoria O (1). En GHC, sumse define como foldl (+) 0, y ¿qué es lo que detiene el análisis de rigurosidad para evitarlo? ¿Lo ejecutaste compilado con optimizaciones?
Will Ness
@WillNess ¿Cuál podría ser la respuesta? sumno sabrá de antemano que la lista es infinita y que, en printsuma, debe evaluarse primero. Y sí, lo compilé con optimizaciones
Angs
no habría una respuesta; pero el cálculo correría en el espacio O (1). Vaya, descubra que, debido al valor predeterminado Integer, los números son ilimitados y la memoria tomada por el resultado actual bignum , de hecho crecería.
Will Ness
1
solo para aclarar, lo que quise decir fue que el cálculo de sum xs = foldl (+) 0 xspuede ejecutarse en una pila constante, como lo haría cualquier ciclo imperativo . foldl' (+) 0 xsCiertamente lo hará. Entonces, lo único que asigna memoria con certeza es el resultado intermedio bignum.
Will Ness
9

C ++ (usando el compilador g ++), 27 23 15 bytes

Gracias a Neop por ayudarme a eliminar 4 bytes.

Esta solución realmente no pierde ninguna memoria porque asigna todo en la pila y por lo tanto causa un desbordamiento de la pila. Es simplemente infinitamente recursivo. Cada recursión hace que se asigne algo de memoria hasta que la pila se desborde.

main(){main();}

Solución alternativa

Esta solución realmente pierde memoria.

main(){for(;;new int);}

Salida de Valgrind

Esta es la salida de Valgrind después de terminar el programa varios segundos después del tiempo de ejecución. Puedes ver que ciertamente está perdiendo memoria.

==2582== LEAK SUMMARY:
==2582==    definitely lost: 15,104,008 bytes in 3,776,002 blocks
==2582==    indirectly lost: 0 bytes in 0 blocks
==2582==      possibly lost: 16 bytes in 4 blocks
==2582==    still reachable: 4 bytes in 1 blocks
==2582==         suppressed: 0 bytes in 0 blocks
Asistente de trigo
fuente
3
El título es engañoso; la pregunta dice "escribir un programa que se ejecute para siempre y continuamente asigne memoria".
NobodyNada - Restablece a Mónica el
Oh, no me di cuenta de que ya enviaste una respuesta cuando envié la mía.
Neop
1
@Neop Bueno, no sabía que podías omitir int hasta que vi los tuyos, así que gracias!
Wheat Wizard
2
No C++, solo el dialecto de g ++: C ++ prohíbe llamar a main; C ++ requiere int main...declaración. Pero la solución sigue siendo clara :-)
Martin Ba
1
De hecho, C ++ prohíbe las llamadas main.
R ..
9

JAVA, 81 79 78 bytes

JAVA (HotSpot) 71 70 bytes

Más corto que otras respuestas de Java en el momento en que publiqué (81, más tarde 79 bytes):

class A{public static void main(String[]a){String x="1";for(;;)x+=x.intern();}}

Según lo sugerido por @Olivier Grégoire, se puede guardar un byte adicional:

class A{public static void main(String[]a){for(String x="1";;)x+=x.intern();}}

Colocar x+=x.intern()como el incremento de bucle for no ayudaría en nada, porque todavía se necesita un punto y coma para finalizar la instrucción for.

Según lo sugerido por @ETHproductions, solo usando x+=xtrabajos también:

class A{public static void main(String[]a){String x="1";for(;;)x+=x;}}

Lo que también puede beneficiarse del consejo de @Olivier Grégoire:

class A{public static void main(String[]a){for(String x="1";;)x+=x;}}

Mis únicas dudas sobre eso es que no se garantiza que se asignen datos en el montón , ya que una JVM eficiente puede darse cuenta fácilmente de que xnunca escapa a la función local. El uso intern()evita esta preocupación porque las cadenas internadas finalmente terminan almacenadas en un campo estático. Sin embargo, HotSpot genera un OutOfMemoryErrorcódigo para ese código, así que supongo que está bien.

Actualización: @Olivier Gregoire también señaló que el x+=xcódigo puede ejecutarse en StringIndexOutOfBoundsExceptionlugar de OOMcuando hay mucha memoria disponible. Esto se debe a que Java usa el tipo de 32 bits intpara indexar matrices (y las cadenas son solo matrices de char). Esto no afecta a la x+=x.intern()solución ya que la memoria requerida para este último es cuadrática en la longitud de la cadena, y por lo tanto debería escalar hasta el orden de 2 ^ 62 bytes asignados.

Daniel deprimido
fuente
Bienvenido a PPCG! No conozco muy bien Java; ¿Qué pasaría si lo hicieras x+=x;?
ETHproductions
puede quitarse un punto y coma quitando x+=x.intern()el último punto y coma del bucle for
masterX244
Buena respuesta. Sabía que tenía que haber algo con las cuerdas intern, pero estaba bastante contento con Inseguro y concluí que dejé de buscar, jaja. Originalmente, esta pregunta especificaba "pérdida de memoria", razón por la cual no hice una respuesta de cadena concat.
Poke
Si su respuesta depende de una implementación específica de Java, y no necesariamente sería portátil para todas las implementaciones de Java, puede colocar la información en el título (por ejemplo # Java (HotSpot), 71 bytes). De esa manera, no necesita preocuparse por la solución que potencialmente hace trampa; los programas específicos de implementación son comunes no solo en el golf, sino también en el mundo más amplio de la programación, y siempre que sepa lo que está haciendo, a veces puede ser más apropiado que un programa portátil para, por ejemplo, fuera del guión.
1
humm ... x+=x;no agota toda la memoria. Con 64 GB, obtengo un StringIndexOutOfBoundsException, no un OOM. Con .intern()todavía me sale el OOM.
Olivier Grégoire
8

Perl 6 , 13 bytes

@= eager 0..*

Explicación:

@ = almacenar el resultado en una matriz sin nombre

eager haga la siguiente lista ansiosa

0 .. * rango infinito a partir de cero

Brad Gilbert b2gills
fuente
8

///, 7 bytes

/a/aa/a

Reemplazar constantemente acon aanáuseas.

Steenbergh
fuente
12
*aad naauseum
timothymh
1
* ad nauseam=>aad naauseaam
Aaron
¿Qué hay de //a/? Eso parece reemplazar para siempre `` (nada) por a, pero no estoy seguro de si esto se especifica exactamente.
Cedric Reichenbach
6

Python 3, 16 bytes

i=9
while 1:i*=i

Esto viene del hecho de que no hay límite para el tamaño entero en Python 3; en cambio, los enteros pueden ocupar tanta memoria como el sistema puede manejar (si algo sobre mi comprensión de esto está mal, corríjame).

artificial
fuente
El título implica que la memoria debe filtrarse. Pero esto en realidad no pierde memoria. El autor probablemente debería aclarar.
Wheat Wizard
6

Óxido, 46 ​​bytes

fn main(){loop{std::mem::forget(Box::new(1))}}

¿Notó algo interesante sobre este programa Rust, que pierde las asignaciones del montón hasta que se queda sin memoria?

Así es, no hay bloque inseguro. Rust garantiza la seguridad de la memoria en un código seguro (sin lectura de datos no inicializados, lectura libre, doble libre, etc.), pero las pérdidas de memoria se consideran perfectamente seguras. Incluso hay una función explícita para hacer que el compilador se olvide de la limpieza de RAII de variables fuera de alcance, que uso aquí.

Harald Korneliussen
fuente
6

Conjunto hexagonal TI-83, 7 bytes

PROGRAM:M
:AsmPrgm
:EF6A4E
:C3959D
:C9

Crea appvars indefinidamente hasta que ERR:MEMORYel sistema operativo arroja uno. Corre con Asm(prgmM). Cuento cada par de dígitos hexadecimales como un byte.

Acosar
fuente
6

Python, 8 bytes

2**9**99

El OP ha permitido la tecnicidad de un programa que técnicamente no se ejecuta "para siempre", pero asigna más memoria de la que cualquier computadora podría manejar. Esto no es un googolplex (eso sería 10**10**100, 11 bytes), pero ingenuamente, la base de registro 2 del número es

>>> 9**99.
2.9512665430652752e+94

es decir, 10 ^ 94 bits para representarlo. WolframAlpha dice que es 10 ^ 76 más grande que la red profunda (tenga en cuenta que hay alrededor de 10 ^ 80 átomos en el universo ).

¿Por qué 2 en lugar de 9 preguntas? No hace mucha diferencia (usar 9 solo aumentaría el número de bits por un factor de log2(9) = 3.2, que ni siquiera cambia el exponente). Pero, por otro lado, el programa se ejecuta mucho más rápido con 2, ya que el cálculo es más simple. Esto significa que llena la memoria inmediatamente, a diferencia de la versión 9, que lleva un poco más de tiempo debido a los cálculos requeridos. No es necesario, pero bueno si quieres "probar" esto (lo que hice).

asmeurer
fuente
5

Jalea , 3 2 bytes

-1 byte gracias a Dennis ( Wwraps)

Un enlace (es decir, función o método), que también funciona como un programa completo, que envuelve recursivamente su entrada en una lista.

La entrada comienza como cero, por lo que la primera pasada crea la lista. [0]
La segunda pasada hace esto. [[0]]
La tercera pasada hace esto [[[0]]]
y así sucesivamente ...


3 byter anterior, que se filtra mucho más rápido:

;Ẇß

concatena recursivamente todas las sublistas contiguas no vacías de su entrada a su entrada.
[0]-> [0,[0]]-> [0,[0],[0],[[0]],[0,[0]]]y así sucesivamente ...

Jonathan Allan
fuente
Si entiendo las reglas correctamente, ‘ßdebería ser suficiente.
Dennis
¿Eso realmente "asigna memoria continuamente" (pensando en Python manteniendo una asignación constante para pequeños ints).
Jonathan Allan
1
Lo suficientemente justo. Sin embargo, aún debe ajustarse a la factura.
Dennis
5

Java 7, 106 bytes

class A{public void finalize(){for(;;)Thread.yield();}public static void main(String[]a){for(;;)new A();}}

Menos golf

class A{
    @Override
    public void finalize(){
        for(;;) {
            Thread.yield();
        }
    }
    public static void main(String[]a){
        for(;;){
            new A();
        }
    }
}

El finalizerecolector de basura llama al método en un objeto cuando la recolección de basura determina que no hay más referencias al objeto. Simplemente he redefinido este método para hacer un bucle para siempre, por lo que el recolector de basura nunca libera la memoria. En el mainbucle, creo nuevos objetos que nunca se limpiarán, por lo que eventualmente se usará toda la memoria disponible.

Java 7 (alternativa divertida), 216 bytes

import sun.misc.*;class A{public static void main(String[]a)throws Exception{java.lang.reflect.Field f=Unsafe.class.getDeclaredField("theUnsafe");f.setAccessible(1>0);for(;;)((Unsafe)f.get(null)).allocateMemory(9);}}

Menos golf

import sun.misc.*;
class A{
    public static void main(String[]a)throws Exception{
        java.lang.reflect.Field f=Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe u = (Unsafe)f.get(null);
        for(;;) {
            u.allocateMemory(9);
        }
    }
}

Esta es una diversión más que cualquier otra cosa. Esta respuesta hace uso de la Unsafebiblioteca Sun, que es una API interna no documentada. Es posible que deba cambiar la configuración del compilador para permitir API restringidas. Unsafe.allocateMemoryasigna una cantidad específica de bytes (sin ninguna verificación de límites) que no está en el montón y no está bajo la administración del recolector de basura de Java, por lo que esta memoria se mantendrá hasta que llame Unsafe.freeMemoryo hasta que jvm se quede sin memoria.

Meter
fuente
1
Me preguntaba si vería Java aquí.
Urna de pulpo mágico
¿El primero solo funciona si el recolector de basura se ejecuta en un subproceso separado?
tbodt
@tbodt sí, pero no creo que este nunca sea el caso. La recolección de basura ocurre en un hilo de demonio llamado recolector de basura
Empuje el
@Poke está garantizado? si no, la respuesta aún está bien, pero debe aclarar que solo funciona si el recolector de basura se ejecuta en su propio hilo
tbodt
@tbodt Creo que sí, pero no estoy seguro, sinceramente.
Poke
5

Haskell, 24 bytes

f x=f$x*x
main=pure$!f 9

El principal problema en Haskell es vencer a la pereza. mainnecesita tener algún IOtipo, por lo que simplemente llamar main=f 9no funcionaría. El uso main=pure(f 9)eleva el tipo de f 9a un IOtipo. Sin embargo, el uso de construcciones como main=pure 9no hace nada, 9se devuelve o se muestra en ninguna parte, sino que simplemente se descarta, por lo que no es necesario evaluar el argumento de pure, por main=pure(f 9)lo tanto , no causa que se asigne ninguna memoria como fno se llama. Para hacer cumplir la evaluación, el $!operador existe. Simplemente aplica una función a un argumento pero primero evalúa el argumento. Por lo tanto, el uso main=pure$!f 9evalúa fy, por lo tanto, asigna continuamente más memoria.

Laikoni
fuente
Cuando se compila, el tiempo de ejecución detecta el bucle y detiene la ejecución
Angs
@Angs compilé con ghc en Windows y sigue asignando memoria felizmente ... Lo detuve en 3GB.
Laikoni
Usar f x=f xobras también, ¿verdad? (−2 bytes)
wchargin
@wchargin No lo creo, f x=f xproduce un bucle infinito, pero sin asignar memoria nueva.
Laikoni
¡Agradable, causando la pérdida de memoria por los cálculos bignum! f!x=x*f(x*x)debería hacerlo a prueba de optimizaciones.
Will Ness
5

dc, 7 bytes

[ddx]dx

[ddx]empuja una cadena que contiene "ddx" a la pila. dxduplica y luego lo ejecuta como código (dejando una copia en la pila). Cuando se ejecuta, hace dos duplicados y luego ejecuta uno, dejando una copia más en la pila cada vez.

faubi
fuente
Espera, ¿entonces esto asignaría exponencialmente la memoria si pudiera ejecutarse en paralelo?
HyperNeutrino
5

Haskell (usando ghc 8.0.1), 11 bytes

m@main=m>>m

Recursión sin cola. mainse llama a sí mismo y luego a sí mismo nuevamente.

nimi
fuente
¿Se asigna esto en el montón o en la pila? (Puedo creerlo; bien puede depender del compilador Haskell en los usos)
1
@ ais523: depende. Haskell no tiene pila de llamadas . El sistema de tiempo de ejecución RTS tiene un área de memoria para la coincidencia de patrones que también se denomina "pila". Esta pila se asigna en el montón. Honestamente, no sé qué está pasando aquí, porque el programa falla con Stack space overflow: current size 33624 bytes.33k parece bastante bajo en contraste con los 6G de memoria total que informa el sistema operativo.
nimi
1
@ ais523: parece que hay un error en la información de la memoria del mensaje de error ghc, por lo que es difícil saber qué sucede exactamente.
nimi
Compilado en GHC 7.10.3 en Ubuntu, esto parece tener una cantidad constante de memoria incluso cuando las optimizaciones están deshabilitadas
Angs
@Angs: hmm, uso ghc 8.0.1 en MacOS. Editaré esto en.
nimi
5

C (Linux), 23 bytes

main(){while(sbrk(9));}

sbrk()incrementa la parte superior del segmento de datos en el número dado de bytes, lo que aumenta efectivamente la cantidad de memoria asignada al programa, al menos como se informa en el VIRTcampo de topsalida. Esto solo funciona en Linux: la implementación de macOS es aparentemente una emulación que solo permite la asignación de hasta 4 MB.


Entonces, una respuesta un poco más general:

C, 25 bytes

main(){while(malloc(9));}

Lo vi en el Monitor de actividad de macOS. Llegó hasta aproximadamente 48 GB, luego, finalmente, el proceso recibió una señal SIGKILL. FWIW mi macbook pro tiene 16 GB. La mayor parte de la memoria utilizada se informó como comprimida.

Tenga en cuenta que la pregunta efectivamente requiere que se escriba cada asignación, lo que no sucede explícitamente aquí. Sin embargo, es importante tener en cuenta que para cada malloc(9)llamada, no solo se asignan los 9 bytes solicitados por el usuario. Para cada bloque asignado, habrá un encabezado malloc que también se asigna desde algún lugar del montón, que necesariamente es escrito por los malloc()internos.

Trauma digital
fuente
Con malloc, no está escribiendo directamente en la memoria ya que malloc no inicializa nada. La memoria solo se asigna porque malloc necesita algo de almacenamiento interno para administrar la memoria. Entonces la respuesta no es realmente estándar, pero supongo que funciona en todas partes de todos modos.
Antzi
@Antzi Sí. Sin embargo, creo que esto todavía funciona porque, aunque la memoria del usuario no se pueda asignar antes de que se escriba, cada malloc()bloque ed debe tener su propio espacio asignado real. Esto funciona en macOS y Ubuntu.
Trauma digital el
La condición en la pregunta de cada página que se está escribiendo no tiene sentido; incluso si desea asumir que un sistema operativo no realiza una contabilidad de compromiso adecuada, independientemente de los detalles de implementación, necesariamente se necesita una cantidad distinta de contabilidad por asignación. Ya sea adyacente a la asignación (haciendo que se toquen las páginas) o no, eventualmente consumirá cantidades arbitrarias de memoria para la contabilidad con (necesariamente) datos distintos de cero.
R ..
Podría obtenerlo un byte más pequeño main(){main(malloc(9));}, pero para no apilar el desbordamiento, necesita una optimización de llamada de cola, y gcc no parece querer hacer eso el main...
R ..
Si reemplaza malloc (9) con calloc (9,9), habrá suficiente memoria asignada para 9 instancias de un bloque de 9 bytes (por lo tanto, entre 81 y 144 bytes, dependiendo de la alineación. Sin embargo, y más importante, calloc ( ) llenará a cero el bloque de memoria, lo que obligará al sistema operativo subyacente a asignarle almacenamiento.
CSM
5

Perl, 4 bytes

do$0

Se ejecuta a sí mismo, en el intérprete actual. Cuando finaliza, la ejecución vuelve al script de llamada, que requiere una pila de llamadas.

primo
fuente
Agradable y breve, aunque no desperdicia memoria rápidamente como la mía.
BenGoldberg
4

Raqueta, 13 bytes

(let l()(l)1)

No estoy del todo seguro si mi respuesta corresponde a esta pregunta. Avíseme si debo eliminar esta respuesta.

Winny
fuente
¿Puedes explicar cómo funciona?
tbodt
1
oh, entonces se está definiendo lcomo una función que hace una recursión sin cola. Yo diría que cuenta.
tbodt
@tbodt sí, tienes razón en el dinero
Winny
4

JavaScript 22 21 17 16 15 Bytes

for(a=0;;)a=[a]

Ahorró 4 bytes envolviendo la lista en otra lista como en la respuesta de @Jonathan Allan's Jelly.

Guardado 1 byte gracias a @ETHProductions

Solución alternativa de 15 bytes (solo funciona con llamadas de cola adecuadas)

f=a=>f([a]);f()
Lmis
fuente
1
En su segundo ejemplo con ES6, ¿no podría simplemente hacerlo f=_=>f();f()? 12 bytes
mordido el
@bitten No estoy seguro. Si cuenta volar la pila de llamadas, entonces esa sin las llamadas de cola adecuadas sería el camino a seguir. Con TCO, no creo que se pierda ningún recuerdo, ¿verdad?
Lmis
ambos me soplan la pila de llamadas . No estoy realmente familiarizado con las llamadas de cola, así que no puedo comentar sobre eso.
mordido el
1
Ah, ya veo, no estaba seguro de cómo el tuyo estaba perdiendo memoria
mordido el
1
Podrías eliminarlo a=0. La primera iteración resultaría ena=[undefined]
Florent
4

Ruby, 11 bytes

loop{$*<<9}

Sigue empujando 9sobre $*, que es una matriz inicialmente que sostiene los argumentos de línea de comandos para el proceso de Ruby.

daniero
fuente
4

05AB1E , 2 bytes

[A

Pruébalo en línea! Seguirá empujando abcdefghijklmnopqrstuvwyxzen la pila por la eternidad.

Todas las posibles soluciones de 2 bytes:

[  # Infinite loop.
 A # Push alphabet.
 0 # Push 0.
 1 # Push 1.
 2 # Push 2.
 3 # Push 3.
 4 # Push 4.
 5 # Push 5.
 6 # Push 6.
 7 # Push 7.
 8 # Push 8.
 9 # Push 9.
 T # Push 10.
 X # Push 1.
 Y # Push 2.
 ® # Push -1.
 ¶ # Push \n.
 º # Push len(stack) > 0, so 0 once then 1 for eternity.
 ð # Push a space.
 õ # Push an empty string.
 ¾ # Push 0.
 ¯ # Push [].
 M # Push -inf.
 ) # Wrap current stack in an array.
Urna de pulpo mágico
fuente
¡Muy minucioso! Agradable.
timothymh
3

Python, 35 bytes

def f(a=[]):a.append(a)
while 1:f()

a nunca se lanza y solo se hace más grande hasta que golpeas un MemoryError

Puede ver la ejecución en Python Tutor .

Noelkd
fuente
1
Puedes hacer a+=a,?
Cyoce
No hay necesidad de una función, aquí está mi golf de ella
FlipTack
@ Flp.Tkc la pregunta cambió después de escribir esta respuesta, hubiera hecho lo que hiciste (+ - par de caracteres) si estuviera en su formato actual.
Noelkd
3

TI-BASIC, 8

:Lbl A
:While 1
:Goto A

(todos los tokens de 1 byte y dos líneas nuevas)

Esto continuamente pierde memoria porque el flujo de control estructurado, como el Whileanticipado por un cierre, Endy empuja algo en la pila (no la pila del sistema operativo, una pila separada en la memoria del montón) para realizar un seguimiento de eso. Pero aquí estamos usando Gotopara dejar el bucle (para que no Endse ejecute nada para eliminar la cosa de la pila), Whilese vuelve a ver, la cosa se empuja de nuevo, etc. Así que sigue empujándolos hasta que se obtieneERR:MEMORY

harold
fuente