Programma più breve che alloca continuamente memoria


49

Scrivi un programma che gira per sempre e alloca più memoria sull'heap più a lungo corre, almeno fino a raggiungere il limite del sistema operativo sulla quantità di memoria che può essere allocata.

Molti kernel non riservano effettivamente la memoria allocata fino a quando non la usi per qualcosa, quindi se il tuo programma è in C o in qualche altra lingua di basso livello dovrai assicurarti di scrivere qualcosa in ogni pagina. Se stai usando un linguaggio interpretato, probabilmente non dovrai preoccuparti di questo.

Il codice più corto vince.


13
Uno stack overflow è una soluzione valida? La memoria deve essere trapelata o semplicemente allocata?
Wheat Wizard

1
@WheatWizard La memoria non deve essere trapelata, ma deve essere allocata più velocemente di quanto non sia deallocata.
martedì

2
L'unica volta che voglio che il mio programma consumi memoria infinita, non riesco a farlo. (reduce conj [] (range))(Clojure) arriva a 737mb, quindi smette di crescere. Idk come non è in continuo aumento. "Pensa" che voglio stampare l'intero elenco alla fine, quindi non dovrebbe buttare via nulla. Molto frustrante.
Carcigenicato il

14
Nota per sé: salvare il codice prima del test. L'introduzione di mem-leaks potrebbe
causare l'

1
Penso che dovresti aggiungere un'altra sfida di golf, simile ma separata da questa, che richiede al programma di consumare memoria più velocemente di una funzione lineare del tempo. Per la sfida attuale , andare in loop per sempre e allocare un singolo byte dovrebbe andare bene. Per la tua nuova sfida, ciò sarebbe insufficiente, ma andare in loop per sempre e raddoppiare la quantità di memoria utilizzata ogni volta sarebbe ok.
BenGoldberg,

Risposte:


46

Funge-98 ( cfunge), 1 byte

9

L'avrei pubblicato prima, ma ho deciso di provarlo e ci è voluto un po 'per riportare il mio computer in uno stato utilizzabile. cfungememorizza lo stack Funge sull'heap del sistema operativo (che è facilmente verificabile eseguendo il programma con un piccolo limite di memoria, cosa che avrei dovuto fare prima!), quindi uno stack infinitamente crescente (come con questo programma, che spinge solo 9ripetutamente; Per impostazione predefinita, i programmi Funge che vanno dalla fine di una riga all'inizio all'inizio assegneranno la memoria per sempre. Questo programma probabilmente funziona anche in alcune implementazioni di Befunge-93.

Più interessante:

"NULL #(4

Questa è stata la mia prima idea ed è un'assegnazione infinita che non si basa sullo stack Funge (anche se fa esplodere anche lo stack Funge). Per cominciare, il "comando inserisce una copia del resto del programma nello stack (è una stringa e il programma si avvolge, quindi la citazione stretta funge anche da citazione aperta). Quindi il Nreflection (non ha alcun significato per impostazione predefinita), facendo sì che il programma venga eseguito all'indietro. Le "piste di nuovo, e spinge il programma per lo stack - viceversa questa volta, con la Nin cima alla pila - allora il programma si avvolge attorno, il caricamento di una libreria con un nome di 4 lettere ( 4(; la NULLlibreria è parte di cfungelibreria standard). NULLdefinisce tutte le lettere maiuscole da riflettere, quindi il Lreflection, il#salta il carico della libreria sulla via del ritorno, i 4push junk di cui non ci preoccupiamo per lo stack e l'intero programma si ripete dall'inizio. Dato che il caricamento di una libreria più volte ha un effetto e richiede che l'elenco dei comandi della libreria sia archiviato una volta per ogni copia della libreria (questo è implicito dalla semantica di Funge-98), perde memoria tramite l'archiviazione non stack (che è un metodo alternativo di definizione di "heap", relativo alla lingua piuttosto che al sistema operativo).


2
Accetterò solo questo ...
tbodt,

È necessario che il numero sia 9? Funzionerebbe anche se fosse 5?
martedì

Qualsiasi cosa spinga nello stack funziona (tranne forse 0; è possibile che l'implementazione di Funge o il sistema operativo possano trovare un modo per ottimizzarlo, dato che la memoria in questione è già piena di zero). Ho appena scelto 9arbitrariamente.

22
Non accetto perché voglio che la mia reputazione sia ancora 666.
decodificato il

7
@tbodt Non è un vero motivo per non accettare. Se vuoi, -1 farò la tua domanda. Quindi, quando accetti, avrai ancora 703 (nota che ora ne hai 703, non 666).
NoOneIsHere

30

Brainfuck, 5 byte

+[>+]

Ciò richiede un interprete che non abbia limiti di lunghezza del nastro.


2
Sono abbastanza sicuro che sia + [> +] altrimenti si fermerebbe semplicemente alla prima iterazione. ;)
Pâris Douady,

Hai ragione, scusa per l'errore di battitura.
vsz,

40
Uno dei rari periodi in cui una soluzione brainfuck è competitiva ...
FlipTack

@ Flp.Tkc Ma perde ancora. Forse vincerà un giorno ...
NoOneIsHere

6
@SeeOneRhino: ha già vinto una volta, battendo tutte le lingue del golf> codegolf.stackexchange.com/questions/8915/…
vsz

22

Bash + coreutils, 5

o

Ruby, 5

`yes`

yesproduce un output infinito. Inserendo yesbacktick si dice alla shell di catturare tutto l'output e quindi eseguirlo come comando. Bash continuerà ad allocare memoria per questa stringa senza fine fino a quando l'heap si esaurisce. Ovviamente l'output risultante finirebbe per essere un comando non valido, ma dovremmo esaurire la memoria prima che ciò accada.

Grazie a @GB per aver sottolineato questo è anche un poliglotta in rubino.


7
Stavo per scrivere lo stesso e chiamarlo un programma Ruby.
GB

1
e perl, penso.
circa

18

Python, 16 byte

Mantiene l'annidamento afino al raggiungimento di un errore:

a=0
while 1:a=a,

Le prime iterazioni (come tuple) si presentano così:

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

E così via e così via.


18

> <> (Pesce), 1 byte

0

Provalo qui!

0 può effettivamente essere sostituito con qualsiasi numero esadecimale 1-f.

Spiegazione

0in> <> crea semplicemente una codebox 1x1 in cui i pesci possono nuotare. Aggiunge costantemente una 0pila nello stack, nuota a destra, a cui fa il giro indietro 0, aggiungendola di nuovo allo stack. Questo andrà avanti per sempre.


2
Ora mi chiedo in quanti altri linguaggi bidimensionali funziona. La maggior parte di essi è basata su stack, dopo tutto.

1
Funziona quasi in Cubix , ma richiede un carattere iniziale .(o qualsiasi carattere non bianco) per spostarlo 0nella riga di esecuzione.
ETHproductions

1
Funziona in Ouroboros , ma non nello stesso modo: l'interprete cerca di leggere 0000000...come un intero intero letterale e la stringa che crea è ciò che continua a prendere più memoria. Un programma che funziona in questo modo a(spinge 10 all'infinito).
DLosc,

12

101 byte Java

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

Catturare il programma principale in un ciclo infinito dopo aver creato e gettato via un oggetto. La garbage collection ha il compito di perdere creando 2 oggetti per ognuno eliminato


bene mi sento un po 'sciocco per non andare con l'ovvio ora, ahah. Mi azzarderei a dire che questo è più elegante del mio
Poke

1
sì, il tuo codice mi ha ricordato di questo fatto con finalize () @poke
masterX244

Penso che potresti accorciarlo sostituendo main con un inizializzatore statico
tbodt

funziona solo con java6 e ho solo versioni più recenti in giro
masterX244

2
ahah usando il bidone della spazzatura per causare una perdita! ottima idea :)
Mark K Cowan il

12

Perl, 12 byte

{$"x=9;redo}

In perl, l' xoperatore, con una stringa a sinistra e un numero a destra, produce una stringa ripetuta. Quindi "abc" x 3valuta "abcabcabc".

L' x=operatore muta l'argomento sinistro, sostituendo il contenuto della variabile alla sua sinistra con il risultato di ripetere il suo contenuto tutte le volte che indica il lato destro.

Perl ha un numero di un numero di variabili costruite in modo strano, una delle quali è $", il cui valore iniziale è un singolo spazio.

L' redooperatore salta all'inizio dell'inclusione {}.

La prima volta che l' x=operatore viene eseguito, cambia il valore di $"da " ""a " ", che è di 9 spazi.

La seconda volta che l' x=operatore ha terminato, cambia il valore di $"a " ", che è 81 spazi.

La terza volta, $"diventa una stringa di spazi lunga 729 byte.

Penso che tu possa vedere dove sta andando :).


Mi hai battuto sul tempo! E il tuo è più corto di tre byte.
Gabriel Benamy,

1
Era solo una questione di cercare in questo sito il ciclo più piccolo :). Inoltre, inizialmente avevo $_.=7nel mio ciclo, ma mi ero reso conto che se avessi potuto usarlo x=avrei esaurito la memoria molto più velocemente, e poi sarei corso perldoc perlvara scegliere qualcosa di adatto.
BenGoldberg,

{$^O++;redo}è più corto di un byte quando ^Oè un singolo chr(15)byte. Sebbene sprecherà memoria a una velocità MOLTO più lenta, per sprecare un byte sono necessarie 1000000000 iterazioni su Windows. Funzionerà su qualsiasi sistema operativo che abbia il suo nome a partire dalla lettera latina.
Oleg V. Volkov,

11

sed, 5 byte

golfed

H;G;D

Utilizzo (qualsiasi input farà)

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

spiegato

#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

Immagine dello schermo

enter image description here

Provalo online!


2
A rigor di termini questo è GNU sed (punto e virgola non è standard sed) ma una nuova riga funzionerebbe altrettanto bene come il punto e virgola comunque.
R ..

10

Haskell, 23 19 byte

main=print$sum[0..]

Stampa la somma di un elenco infinito


Questo è un bel modo per applicare la valutazione ed è anche molto compatto. +1
Esolanging Fruit

un compilatore potrebbe benissimo eseguirlo nella memoria O (1). In GHC, sumè definito come foldl (+) 0, e cosa deve fermare l'analisi di rigore per dare il via, per evitare lo scoppio del colpo? L'hai eseguito compilato con ottimizzazioni?
Will Ness,

@WillNess Quale potrebbe essere la risposta? sumnon saprà in anticipo che l'elenco è infinito e per printla somma deve essere valutato prima. E sì, l'ho compilato con ottimizzazioni
Angs

non ci sarebbe una risposta; ma il calcolo verrebbe eseguito nello spazio O (1). Spiacenti, a causa del fatto che, a causa del default Integer, i numeri sono illimitati e la memoria occupata dal risultato attuale del bignum sarebbe effettivamente cresciuta.
Will Ness,

1
solo per chiarire, intendevo dire che il calcolo di sum xs = foldl (+) 0 xspuò essere eseguito in stack costante, come farebbe qualsiasi ciclo imperativo . foldl' (+) 0 xscertamente lo farà. Quindi l'unica cosa che alloca la memoria per certo, è il risultato intermedio del bignum.
Will Ness,

9

C ++ (usando il compilatore g ++), 27 23 15 byte

Grazie a Neop per avermi aiutato a rimuovere 4 byte

Questa soluzione non perde davvero memoria perché alloca tutto nello stack e causa quindi uno overflow dello stack. È semplicemente infinitamente ricorsivo. Ogni ricorsione provoca l'allocazione di un po 'di memoria fino a quando lo stack trabocca.

main(){main();}

Soluzione alternativa

Questa soluzione perde effettivamente memoria.

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

Uscita Valgrind

Questo è l'output di Valgrind dopo aver terminato il programma per alcuni secondi nel tempo di esecuzione. Puoi vedere che è sicuramente una perdita di 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

3
Il titolo è fuorviante; la domanda dice "scrivere un programma che gira per sempre e alloca continuamente memoria".
NobodyNada - Ripristina Monica il

Oh, non avevo capito che hai già inviato una risposta quando ho inviato la mia.
Neop,

1
@Neop Beh, non sapevo che potessi ommettere int fino a quando non ho visto i tuoi, grazie!
Wheat Wizard

2
No C++, solo il dialetto g ++: C ++ proibisce di chiamare main; C ++ richiede una int main...dichiarazione. Ma la soluzione è ancora pulita :-)
Martin Ba

1
In effetti, C ++ proibisce la chiamata main.
R ..

9

GIAVA, 81 79 78 byte

JAVA (HotSpot) 71 70 byte

Più breve delle altre risposte Java al momento della pubblicazione (81, dopo 79 byte):

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

Come suggerito da @Olivier Grégoire, è possibile salvare un ulteriore byte:

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

Il posizionamento x+=x.intern()come incremento del ciclo for non aiuterebbe nulla, poiché è ancora necessario un punto e virgola per terminare l'istruzione for.

Come suggerito da @ETHproductions, anche solo usando le x+=xopere:

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

Che può anche beneficiare del consiglio di @Olivier Grégoire:

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

Il mio unico dubbio è che non è garantito l'allocazione dei dati sull'heap , poiché una JVM efficiente può facilmente rendersi conto che xnon sfugge mai alla funzione locale. L'uso intern()evita questa preoccupazione perché le stringhe internate finiscono per essere archiviate in un campo statico. Tuttavia, HotSpot genera un OutOfMemoryErrorcodice per quel codice, quindi immagino che vada bene.

Aggiornamento: @Olivier Gregoire ha anche sottolineato che il x+=xcodice può essere eseguito StringIndexOutOfBoundsExceptionpiuttosto che OOMquando è disponibile molta memoria. Questo perché Java utilizza il inttipo a 32 bit per indicizzare le matrici (e le stringhe sono solo matrici di char). Ciò non influisce sulla x+=x.intern()soluzione in quanto la memoria richiesta per quest'ultima è quadratica nella lunghezza della stringa e dovrebbe pertanto ridimensionarsi nell'ordine di 2 ^ 62 byte allocati.


Benvenuti in PPCG! Non conosco molto bene Java; cosa accadrebbe se lo facessi x+=x;?
ETHproductions

puoi radere un punto e virgola mettendo x+=x.intern()dietro l'ultimo punto e virgola del ciclo for
masterX244

Bella risposta. Sapevo che doveva esserci qualcosa con le stringhe, internma ero abbastanza contento di Unsafe e ho finito per smettere di guardare, ahah. Inizialmente questa domanda specificava "perdita di memoria", motivo per cui non ho fatto solo una risposta concat per stringa.
Poke

Se la tua risposta dipende da un'implementazione specifica di Java e non è necessariamente portabile a tutte le implementazioni Java, puoi inserire le informazioni nel titolo (ad es # Java (HotSpot), 71 bytes.). In questo modo, non è necessario preoccuparsi della soluzione che potrebbe barare; i programmi specifici per l'implementazione sono comuni non solo nel golf, ma anche nel più ampio mondo della programmazione, e finché sei consapevole di ciò che stai facendo a volte può essere più appropriato di un programma portatile per, diciamo, uno- fuori script.

1
humm ... x+=x;non esaurisce l'intero ricordo. Con 64 GB, ottengo un StringIndexOutOfBoundsException, non un OOM. Con .intern()ottengo ancora l'OOM.
Olivier Grégoire,

8

Perl 6 , 13 byte

@= eager 0..*

Spiegazione:

@ = archivia il risultato in un array senza nome

eager rendere desideroso il seguente elenco

0 .. * intervallo infinito a partire da zero


8

///, 7 byte

/a/aa/a

Sostituire costantemente acon aa, fino alla nausea.


12
*aad naauseum
Timothymh,

1
* ad nauseam=>aad naauseaam
Aaron,

Che dire //a/? Questo sembra sostituire per sempre `` (niente) con a, ma non sono sicuro se questo è esattamente specificato.
Cedric Reichenbach,

6

Python 3, 16 byte

i=9
while 1:i*=i

Ciò deriva dal fatto che in Python 3 non vi sono limiti alla dimensione intera; invece, i numeri interi possono occupare tutta la memoria che il sistema è in grado di gestire (se qualcosa nella mia comprensione di questo è sbagliato, correggimi).


Il titolo implica che la memoria dovrebbe essere trapelata. Ma questo non perde effettivamente memoria. L'autore dovrebbe probabilmente chiarire.
Wheat Wizard

6

Ruggine, 46 byte

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

Notate qualcosa di interessante su questo programma Rust, perdendo allocazioni di heap fino a esaurimento della memoria?

Esatto, nessun blocco non sicuro. Rust garantisce la sicurezza della memoria in un codice sicuro (nessuna lettura di dati non inizializzati, lettura dopo libera, doppia libera ecc.), Ma le perdite di memoria sono considerate perfettamente sicure. C'è anche una funzione esplicita per far dimenticare al compilatore la pulizia RAII di variabili fuori ambito, che uso qui.


6

Gruppo esadecimale TI-83, 7 byte

PROGRAM:M
:AsmPrgm
:EF6A4E
:C3959D
:C9

Crea appvars indefinitamente fino a quando non ERR:MEMORYviene lanciato dal SO. Corri con Asm(prgmM). Conto ogni coppia di cifre esadecimali come un byte.


6

Python, 8 byte

2**9**99

L' OP ha consentito la tecnicità di un programma che tecnicamente non viene eseguito "per sempre", ma alloca più memoria di quella che un computer potrebbe gestire. Questo non è abbastanza un googolplex (che sarebbe 10**10**100, 11 byte), ma ingenuamente, log base 2 del numero è

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

cioè, 10 ^ 94 bit per rappresentarlo. WolframAlpha lo pone come 10 ^ 76 più grande della rete profonda (tieni presente che ci sono circa 10 ^ 80 atomi nell'universo ).

Perché 2 invece di 9 chiedete? Non fa molta differenza (l'uso di 9 aumenterebbe il numero di bit solo di un fattore di log2(9) = 3.2, che non cambia nemmeno l'esponente). D'altra parte, il programma funziona molto più velocemente con 2, poiché il calcolo è più semplice. Ciò significa che riempie immediatamente la memoria, a differenza della versione 9, che richiede un po 'più di tempo a causa dei calcoli richiesti. Non necessario, ma bello se si vuole "testare" questo (cosa che ho fatto).


5

Gelatina , 3 2 byte

-1 byte grazie a Dennis ( Wwraps)

Un collegamento (ovvero una funzione o un metodo), che funziona anche come un programma completo, che avvolge ricorsivamente il suo input in un elenco.

L'ingresso inizia come zero, quindi il primo passaggio crea l'elenco. [0]
Il secondo passaggio quindi effettua questo. [[0]]
Il terzo passaggio effettua quindi questo [[[0]]]
e così via ...


Precedente 3 byter, che perde molto più velocemente:

;Ẇß

concatena ricorsivamente tutte le liste secondarie contigue non vuote del suo input al suo input.
[0]-> [0,[0]]-> [0,[0],[0],[[0]],[0,[0]]]e così via ...


Se capisco correttamente le regole, ‘ßdovrebbe essere abbondante.
Dennis,

Fa davvero "allocare continuamente memoria" (pensando a Python mantenendo un'allocazione costante per piccoli ints).
Jonathan Allan,

1
Giusto. dovrebbe comunque adattarsi al conto.
Dennis,

5

Java 7, 106 byte

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

Meno golfato

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

Il finalizemetodo viene chiamato su un oggetto dal Garbage Collector quando Garbage Collection determina che non ci sono più riferimenti all'oggetto. Ho semplicemente ridefinito questo metodo per eseguire il ciclo per sempre in modo che il Garbage Collector non liberi mai effettivamente la memoria. Nel mainciclo creo nuovi oggetti che non verranno mai ripuliti, quindi alla fine questo utilizzerà tutta la memoria disponibile.

Java 7 (alternativa divertente), 216 byte

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);}}

Meno golfato

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);
        }
    }
}

Questo è divertente più di ogni altra cosa. Questa risposta utilizza la Unsafelibreria Sun, che è un'API interna non documentata. Potrebbe essere necessario modificare le impostazioni del compilatore per consentire le API limitate. Unsafe.allocateMemoryalloca una quantità specificata di byte (senza alcun controllo dei limiti) che non si trova nell'heap e non è gestito da java garbage collector in modo che questa memoria Unsafe.freeMemoryrimanga attiva fino a quando non si chiama o fino a quando jvm si esaurisce.


1
Mi chiedevo se avrei visto Java qui.
Magic Octopus Urn

Il primo non funziona solo se il Garbage Collector è in esecuzione in un thread separato?
martedì

@tbodt sì, ma non credo che non sia mai così. La garbage collection avviene in un thread demone chiamato garbage collector
Poke

@Poke è garantito? in caso contrario la risposta è ancora valida, ma dovresti chiarire che funziona solo se il Garbage Collector viene eseguito nel suo thread
tbodt

@tbodt Penso di sì, ma non ne sono certo, onestamente.
Poke

5

Haskell, 24 byte

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

Il problema principale in Haskell è quello di battere la pigrizia. maindeve avere un certo IOtipo, quindi la semplice chiamata main=f 9non funzionerebbe. L'utilizzo main=pure(f 9)solleva il tipo di f 9un IOtipo. Tuttavia, l'utilizzo di costrutti come main=pure 9non fa nulla, 9viene restituito o visualizzato da nessuna parte ma semplicemente scartato, quindi non è necessario valutare l'argomento di pure, quindi main=pure(f 9)non viene allocata alcuna memoria come fnon viene chiamata. Per imporre la valutazione, l' $!operatore esiste. Si applica semplicemente una funzione a un argomento ma valuta prima l'argomento. Quindi l'utilizzo di main=pure$!f 9valuta fe quindi alloca continuamente più memoria.


Una volta compilato, il runtime rileva il loop e interrompe l'esecuzione
Angs

@Angs Ho compilato con ghc su Windows e continua a distribuire felicemente la memoria ... L'ho fermato a 3 GB.
Laikoni,

Anche usare f x=f xfunziona, vero? (−2 byte)
wchargin

@wchargin Non credo, f x=f xproduce un ciclo infinito, ma senza allocare nuova memoria.
Laikoni,

Bello, causando l'esplosione della memoria dai calcoli del bignum! f!x=x*f(x*x)dovrebbe renderlo a prova di ottimizzazione.
Will Ness,

5

dc, 7 byte

[ddx]dx

[ddx]invia una stringa contenente "ddx" nello stack. dxlo duplica, quindi lo esegue come codice (lasciando una copia nello stack). Quando eseguito, crea due duplicati, quindi ne esegue uno, lasciando una copia in più ogni volta.


Aspetta, quindi questo allocare esponenzialmente la memoria se potesse funzionare in parallelo?
HyperNeutrino il

5

Haskell (usando ghc 8.0.1), 11 byte

m@main=m>>m

Ricorsione della coda. mainchiama se stesso e poi di nuovo se stesso.


Questo si alloca nell'heap o nello stack? (Posso crederci neanche; potrebbe benissimo dipendere dal compilatore Haskell negli usi.)

1
@ ais523: dipende. Haskell non ha stack di chiamate . Il sistema di runtime RTS ha un'area di memoria per il pattern matching che è anche chiamato "stack". Questo stack è allocato sull'heap. Onestamente, non so cosa stia succedendo qui, perché il programma fallisce con Stack space overflow: current size 33624 bytes.33k sembra abbastanza basso in contrasto con il 6G di memoria totale che il sistema operativo sta segnalando.
nimi

1
@ ais523: sembra che ci sia un bug nelle informazioni sulla memoria del messaggio di errore ghc, quindi è difficile dire cosa succede esattamente.
nimi

Compilato su GHC 7.10.3 su Ubuntu, questo sembra richiedere una quantità costante di memoria anche quando le ottimizzazioni sono disabilitate
Angs

@Angs: hmm, io uso ghc 8.0.1 su MacOS. Lo modificherò tra.
nimi

5

C (linux), 23 byte

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

sbrk()incrementa la parte superiore del segmento di dati del numero dato di byte, aumentando così in modo efficace la quantità di memoria allocata al programma - almeno come riportato nel VIRTcampo di topoutput. Funziona solo su Linux: l'implementazione di macOS è apparentemente un'emulazione che consente solo l'allocazione fino a 4 MB.


Quindi una risposta leggermente più generale:

C, 25 byte

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

L'ho visto su macOS Activity Monitor. È arrivato fino a circa 48 GB, quindi alla fine il processo ha ricevuto un segnale SIGKILL. FWIW il mio macbook pro ha 16 GB. La maggior parte della memoria utilizzata è stata segnalata come compressa.

Si noti che la domanda richiede effettivamente che ogni allocazione venga scritta, cosa che non accade esplicitamente qui. Tuttavia, è importante notare che per ogni malloc(9)chiamata non sono allocati solo i 9 byte richiesti dall'utente. Per ogni blocco allocato ci sarà un'intestazione malloc che è allocata anche da qualche parte sull'heap, che è necessariamente scritta dagli malloc()interni.


Con malloc, non stai scrivendo direttamente nella memoria poiché malloc non inizializza nulla. La memoria è allocata solo perché malloc necessita di memoria interna per la gestione della memoria. Quindi la risposta non è proprio standard ma immagino che funzioni comunque ovunque.
Antzi

@Antzi Sì. Tuttavia, penso che funzioni ancora perché, anche se la memoria dell'utente potrebbe non essere allocata prima di essere scritta, ogni malloc()blocco ed deve avere il suo spazio allocato reale. Funziona su macOS e Ubuntu.
Digital Trauma

La condizione nella domanda di ogni pagina in cui si scrive è piuttosto insignificante; anche se si desidera presumere che un sistema operativo non esegua correttamente la contabilità dei commit, indipendentemente dai dettagli di implementazione, è necessaria una quantità di contabilità diversa da zero per allocazione. Indipendentemente dal fatto che sia adiacente all'allocazione (che consente di toccare le pagine) o meno, alla fine consumerà quantità arbitrarie di memoria per la contabilità con (necessariamente) dati diversi da zero.
R ..

Potresti ridurlo di un byte in quanto main(){main(malloc(9));}, ma per non impilare l'overflow, ha bisogno dell'ottimizzazione delle chiamate di coda, e gcc non sembra volerlo fare su main...
R ..

Se si sostituisce malloc (9) con calloc (9,9), verrà allocata memoria sufficiente per 9 istanze di un blocco di 9 byte (quindi tra 81 e 144 byte, a seconda dell'allineamento. Tuttavia, e soprattutto, calloc ( ) riempirà zero il blocco di memoria, costringendo il sistema operativo sottostante ad allocare spazio di archiviazione.
CSM

5

Perl, 4 byte

do$0

Si esegue, nell'interprete corrente. Al termine, l'esecuzione torna allo script chiamante, che richiede uno stack di chiamate.


Bello e breve, anche se non spreca memoria rapidamente come il mio.
BenGoldberg,

4

Racchetta, 13 byte

(let l()(l)1)

Non sono del tutto sicuro se la mia risposta rientri in questa domanda. Per favore fatemi sapere se dovrei rimuovere questa risposta.


Puoi spiegare come funziona?
martedì

1
oh, quindi si sta definendo luna funzione che esegue la ricorsione senza coda. direi che conta.
martedì

@tbodt sì, hai ragione sul denaro
Winny,

4

JavaScript 22 21 17 16 15 byte

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

Hai salvato 4 byte avvolgendo l'elenco in un altro elenco come nella risposta Jelly di @Jonathan Allan.

Salvato 1 byte grazie a @ETHProductions

Soluzione alternativa 15 byte (funziona solo con chiamate di coda appropriate)

f=a=>f([a]);f()

1
Nel tuo secondo esempio con ES6, non potresti semplicemente farlo f=_=>f();f()? 12 byte
morso

@bitten non ne sono sicuro. Se conta per far esplodere lo stack di chiamate, allora quello senza chiamate di coda adeguate sarebbe la strada da percorrere. Con TCO, non penso che ci sarebbe una perdita di memoria, vero?
Lmis,

entrambi fanno saltare la pila di chiamate per me . non ho molta familiarità con le chiamate di coda, quindi non posso commentarlo.
morso il

1
ah, capisco, non ero sicuro di come la tua memoria perdesse
morso il

1
Potresti rimuovere a=0. La prima iterazione si tradurrebbe ina=[undefined]
Florent il

4

Rubino, 11 byte

loop{$*<<9}

Continua a spingere 9su $*, che è un array che inizialmente contiene gli argomenti della riga di comando al processo Ruby.


4

05AB1E , 2 byte

[A

Provalo online! Continuerà a spingereabcdefghijklmnopqrstuvwyxz in pila per l'eternità.

Tutte le possibili soluzioni a 2 byte:

[  # 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.

Molto accurato! Bello.
Timothymh,

3

Python, 35 byte

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

a non viene mai rilasciato e diventa più grande fino a quando non si colpisce a MemoryError

Puoi visualizzare l'esecuzione su Python Tutor .


1
Si può fare a+=a,?
Cyoce,

Non c'è bisogno di una funzione, ecco il mio punto di forza
FlipTack

@ Flp.Tkc la domanda è stata cambiata dopo che ho scritto questa risposta avrei fatto quello che hai fatto (+ - un paio di caratteri) se fosse nel suo formato attuale.
Noelkd,

3

TI-BASIC, 8

:Lbl A
:While 1
:Goto A

(tutti i token da 1 byte e due newline)

Ciò perde continuamente memoria perché il flusso di controllo strutturato, come la Whileprevisione di essere chiuso da un Ende spinge qualcosa nello stack (non lo stack del sistema operativo, uno stack separato nella memoria dell'heap) per tenerne traccia. Ma qui stiamo usando Gotoper abbandonare il loop (quindi non Endviene eseguito per rimuovere l'oggetto dallo stack), Whileviene visto di nuovo, l'oggetto viene spinto di nuovo, ecc. Quindi continua a spingerli fino a quando non si ottieneERR:MEMORY

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.