Kürzestes Programm, das kontinuierlich Speicher reserviert

49

Schreiben Sie ein Programm, das für immer ausgeführt wird und das mehr und mehr Speicher auf dem Heap reserviert, je länger es ausgeführt wird, zumindest bis Sie die Grenze des Betriebssystems für den verfügbaren Speicher erreichen.

Viele Kernel reservieren keinen Speicherplatz, den Sie zuweisen, bis Sie ihn für etwas verwenden. Wenn Ihr Programm also in C oder einer anderen einfachen Sprache ausgeführt wird, müssen Sie sicherstellen, dass Sie auf jeder Seite etwas schreiben. Wenn Sie eine interpretierte Sprache verwenden, müssen Sie sich darüber wahrscheinlich keine Gedanken machen.

Kürzester Code gewinnt.

tbodt
quelle
13
Ist ein Stapelüberlauf eine gültige Lösung? Muss der Speicher durchgesickert oder nur zugewiesen werden?
Wheat Wizard
1
@WheatWizard Der Speicher muss nicht durchgesickert sein, aber er muss schneller zugewiesen werden, als er freigegeben wurde.
1.
2
Das eine Mal, wenn ich möchte, dass mein Programm unendlichen Speicher verbraucht, kann ich es nicht erreichen. (reduce conj [] (range))(Clojure) erreicht bis zu 737 MB und hört dann einfach auf zu wachsen. Idk, wie es nicht ständig steigt. Es "denkt", dass ich die gesamte Liste am Ende ausdrucken möchte, damit nichts weggeworfen wird. Sehr frustrierend.
Carcigenicate
14
Hinweis für sich selbst: Speichern Sie den Code vor dem Testen. Das Einführen von mem-leaks kann zum Absturz von IDE führen ...
steenbergh
1
Ich denke, Sie sollten eine weitere Golfherausforderung hinzufügen, die dieser ähnlich, aber getrennt ist und erfordert, dass das Programm Speicher schneller verbraucht als eine lineare Funktion der Zeit. Für die aktuelle Herausforderung sollte es in Ordnung sein, eine Endlosschleife auszuführen und ein einzelnes Byte zuzuweisen. Für Ihre neue Herausforderung wäre das nicht ausreichend, aber eine Endlosschleife und die Verdoppelung des jeweils verwendeten Speichers wären in Ordnung.
BenGoldberg

Antworten:

46

Funge-98 ( cfunge), 1 Byte

9

Ich hätte dies früher gepostet, habe mich aber dazu entschlossen, es zu testen, und es dauerte eine Weile, bis mein Computer wieder einsatzbereit war. cfungespeichert den Funge-Stack auf dem Heap des Betriebssystems (was leicht zu überprüfen ist, indem das Programm mit einer kleinen Speicherbegrenzung ausgeführt wird, was ich früher hätte tun sollen!), also einen unendlich wachsenden Stack (wie bei diesem Programm, das nur 9wiederholt ausgeführt wird); Funge-Programme, die standardmäßig vom Ende einer Zeile bis zum Anfang umgebrochen werden, weisen Speicherplatz für immer zu. Dieses Programm funktioniert wahrscheinlich auch in einigen Befunge-93-Implementierungen.

Interessanter:

"NULL #(4

Dies war meine erste Idee und ist eine unendliche Zuweisung, die sich nicht auf den Funge-Stapel stützt (obwohl sie auch den Funge-Stapel in die Luft sprengt). Zunächst legt der "Befehl eine Kopie des restlichen Programms im Stapel ab (es ist eine Zeichenfolge, und das Programm wird umgebrochen, sodass das schließende Anführungszeichen auch als offenes Anführungszeichen dient). Dann Nspiegelt sich das wieder (es hat standardmäßig keine Bedeutung) und das Programm wird rückwärts ausgeführt. Das "Programm wird erneut ausgeführt und schiebt das Programm auf den Stapel - umgekehrt, diesmal mit dem Noberen Rand des Stapels - , woraufhin das Programm einen Umlauf ausführt und eine Bibliothek mit einem 4 - Buchstaben - Namen lädt ( 4(; die NULLBibliothek ist Teil von cfungeStandardbibliothek). NULLDefiniert alle Großbuchstaben, die Lreflektiert werden sollen#Überspringt das Laden der Bibliothek auf dem Rückweg, verschiebt den 4uns unbekannten Junk auf den Stack und wiederholt das gesamte Programm von Anfang an. Da das mehrfache Laden einer Bibliothek eine Auswirkung hat und die Befehlsliste der Bibliothek für jede Kopie der Bibliothek einmal gespeichert werden muss (dies wird durch die Semantik von Funge-98 impliziert), führt dies zu einem Speicherverlust über einen Nicht-Stapelspeicher (bei dem es sich um einen handelt) alternative Methode zum Definieren von "Heap" in Bezug auf die Sprache und nicht auf das Betriebssystem.


quelle
2
Ich werde das nur akzeptieren ...
bis zum
Muss die Zahl 9 sein? Würde es auch funktionieren, wenn es 5 wäre?
1.
Alles, was auf den Stack geschoben wird, funktioniert (außer möglicherweise 0; es ist möglich, dass die Funge-Implementierung oder das Betriebssystem einen Weg finden, dies zu optimieren, da der betreffende Speicher bereits mit Nullen gefüllt ist). Ich habe nur 9willkürlich ausgewählt.
22
Inakzeptabel, weil ich möchte, dass mein Ruf immer noch 666 ist.
bis
7
@tbodt Kein wirklicher Grund, nicht zu akzeptieren. Wenn Sie möchten, werde ich -1 Ihre Frage. Wenn Sie akzeptieren, haben Sie noch 703 (beachten Sie, dass Sie jetzt 703 haben, nicht 666).
NoOneIsHere
30

Brainfuck, 5 Bytes

+[>+]

Dies erfordert einen Interpreter, der die Länge des Bandes nicht begrenzt.

vsz
quelle
2
Ich bin mir ziemlich sicher, dass es + [> +] ist, oder es würde einfach bei der ersten Iteration aufhören. ;)
Pâris Douady
Du hast recht, entschuldige den Tippfehler.
vsz
40
Eine der seltenen
Situationen, in
@Flp.tkc Aber es verliert immer noch. Vielleicht wird es gewinnen , einen Tag ...
NoOneIsHere
6
@SeeOneRhino: Es hat bereits einmal gewonnen und alle Golfsprachen
geschlagen
22

Bash + Coreutils, 5

oder

Rubin, 5

`yes`

yesproduziert endlose Ausgabe. Durch das yesEinfügen von Backticks wird die Shell angewiesen, alle Ausgaben zu erfassen und diese Ausgabe dann als Befehl auszuführen. Bash reserviert weiterhin Speicher für diese unendliche Zeichenfolge, bis der Heap-Speicher voll ist. Natürlich würde die resultierende Ausgabe ein ungültiger Befehl sein, aber wir sollten keinen Speicher mehr haben, bevor dies geschieht.

Vielen Dank an @ GB für den Hinweis, dass dies auch ein Polyglott in Rubin ist.

Digitales Trauma
quelle
7
Ich wollte dasselbe schreiben und es ein Ruby-Programm nennen.
GB
1
und Perl, denke ich.
abligh
18

Python, 16 Bytes

Verschachtelt so lange, abis ein Fehler auftritt:

a=0
while 1:a=a,

Die ersten paar Iterationen (als Tupel) sehen so aus:

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

und so weiter und so fort.

FlipTack
quelle
18

> <> (Fisch), 1 Byte

0

Probieren Sie es hier aus!

0 kann tatsächlich durch eine beliebige Hexadezimalzahl 1-f ersetzt werden.

Erläuterung

0in> <> erstellt einfach eine 1x1-Codebox, in der der Fisch schwimmen kann. Sie fügt 0dem Stapel ständig ein hinzu , schwimmt nach rechts, umläuft 0den Stapel und fügt ihn erneut dem Stapel hinzu. Dies wird für immer so weitergehen.

redstarcoder
quelle
2
Jetzt frage ich mich, in wie vielen anderen zweidimensionalen Sprachen dies funktioniert. Die meisten von ihnen sind schließlich stapelbasiert.
1
Funktioniert fast in Cubix , erfordert jedoch ein führendes Zeichen. (oder ein beliebiges Zeichen ohne Leerzeichen), um das 0in die Ausführungslinie zu verschieben.
ETHproductions
1
Funktioniert in Ouroboros , aber nicht auf die gleiche Weise: Der Interpreter versucht, 0000000...als einzelnes Integer-Literal zu lesen , und die Zeichenfolge, die er aufbaut, nimmt immer mehr Speicherplatz in Anspruch. Ein Programm, das so funktioniert wie dieses, wäre a(drückt 10 unendlich).
DLosc
12

Java 101 Bytes

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

Aufrufen des Hauptprogramms in einer Endlosschleife nach dem Erstellen und Wegwerfen eines Objekts. Die Garbage Collection übernimmt das Lecken, indem für jedes gelöschte Objekt 2 Objekte erstellt werden

masterX244
quelle
Nun, ich fühle mich ein bisschen albern, weil ich jetzt nicht mit dem Offensichtlichen gehe, haha. Ich wage zu sagen, das ist eleganter als meins
Poke
1
Ja, Ihr Code erinnerte mich an diese Tatsache mit der finalize () @poke
masterX244
Ich denke, Sie könnten es kürzer machen, indem Sie main durch einen statischen Initialisierer
ersetzen
Funktioniert nur bis Java6 und ich habe nur höhere Versionen im
Angebot
2
haha mit dem müllsammler ein leck verursachen! großartige Idee :)
Mark K Cowan
12

Perl, 12 Bytes

{$"x=9;redo}

In Perl erzeugt der xOperator mit einer Zeichenfolge links und einer Zahl rechts eine wiederholte Zeichenfolge. Also "abc" x 3bewertet zu "abcabcabc".

Der x=Operator mutiert das linke Argument und ersetzt den Inhalt der Variablen auf der linken Seite mit dem Ergebnis, dass der Inhalt so oft wiederholt wird, wie es die rechte Seite angibt.

Perl hat eine Reihe von einer Reihe von seltsam in Variablen gebaut genannt, von denen eines $", dessen Anfangswert ist ein Leerzeichen.

Der redoBediener springt an den Anfang der Anlage {}.

Wenn der x=Operator das erste Mal ausgeführt wird, ändert er den Wert von $"von " ""bis" " ", was 9 Leerzeichen entspricht.

Wenn der x=Operator das zweite Mal ausgeführt wird, ändert er den Wert von $"auf " ", was 81 Leerzeichen entspricht.

Das dritte Mal $"wird eine 729 Byte lange Zeichenfolge von Leerzeichen.

Ich denke, Sie können sehen, wohin das führt :).

BenGoldberg
quelle
Du warst schneller als ich! Und deins ist drei Bytes kürzer.
Gabriel Benamy
1
Es war nur eine Frage der Suche auf dieser Website nach der kleinsten Schleife :). Außerdem hatte ich anfangs $_.=7meine Schleife inne, aber mir wurde klar, wenn ich sie verwenden könnte x=, würde der Speicher viel schneller ausgehen und dann lief ich los perldoc perlvar, um etwas Passendes auszuwählen.
BenGoldberg
{$^O++;redo}ist ein Byte kürzer, wenn ^Oes sich um ein einzelnes chr(15)Byte handelt. Es wird zwar viel langsamer Speicher verschwenden - unter Windows sind 1000000000 Iterationen erforderlich, um ein Byte zu verschwenden. Funktioniert auf jedem Betriebssystem, dessen Name mit einem lateinischen Buchstaben beginnt.
Oleg V. Volkov
11

sed, 5 bytes

Golf gespielt

H;G;D

Verwendung (jede Eingabe ist ausreichend)

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

Erklärt

#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

Bildschirmfoto

Bildbeschreibung hier eingeben

Probieren Sie es online!

Zeppelin
quelle
2
Genau genommen ist dies GNU sed (Semikolon ist nicht Standard sed), aber ein Zeilenumbruch würde sowieso genauso gut funktionieren wie das Semikolon.
R ..
10

Haskell, 23 19 Bytes

main=print$sum[0..]

Gibt die Summe einer unendlichen Liste aus

Angs
quelle
Dies ist eine gute Möglichkeit, die Bewertung durchzusetzen, und sie ist auch sehr kompakt. +1
Esolanging Fruit
Ein Compiler könnte dies sehr gut im O (1) -Speicher ausführen. In GHC sumist definiert als foldl (+) 0, und was die Strenge Analyse zu stoppen, um zu treten, um den Thunk-Ausbruch zu verhindern? Haben Sie es mit Optimierungen kompiliert ausgeführt?
Will Ness
@ WillNess Was könnte die Antwort sein? sumIch werde nicht im Voraus wissen, dass die Liste unendlich ist und bis printzur Summe muss sie zuerst ausgewertet werden. Und ja, ich habe es mit Optimierungen zusammengestellt
Angs
es würde keine Antwort geben; aber die Berechnung würde im O (1) Raum laufen. Hoppla, Integerstelle sicher, dass die Zahlen aufgrund der Standardeinstellung unbegrenzt sind und die Erinnerung, die das aktuelle Bignum- Ergebnis beansprucht , in der Tat zunehmen würde.
Will Ness
1
Um das zu verdeutlichen, meinte ich, dass die Berechnung von sum xs = foldl (+) 0 xsin einem konstanten Stapel ausgeführt werden kann, wie es jede imperative Schleife tun würde. foldl' (+) 0 xssicherlich wird. Das einzige, was mit Sicherheit Speicherplatz zuweist, ist das Zwischenergebnis.
Will Ness
9

C ++ (mit g ++ - Compiler), 27 23 15 Bytes

Vielen Dank an Neop, der mir geholfen hat, 4 Bytes zu entfernen

Diese Lösung führt zu keinem wirklichen Speicherverlust, da sie alles auf dem Stapel zuordnet und somit einen Stapelüberlauf verursacht. Es ist einfach unendlich rekursiv. Bei jeder Rekursion wird Speicher zugewiesen, bis der Stapel überläuft.

main(){main();}

Alternative Lösung

Diese Lösung verliert tatsächlich Speicher.

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

Valgrind Ausgang

Dies ist der Valgrind-Ausgang, nachdem das Programm einige Sekunden nach Ablauf der Laufzeit beendet wurde. Sie können sehen, dass es sicherlich Speicherlecks gibt.

==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
Weizen-Assistent
quelle
3
Der Titel ist irreführend; Die Frage lautet: "Schreiben Sie ein Programm, das für immer läuft und kontinuierlich Speicher zuweist."
NobodyNada
Oh, ich habe nicht bemerkt, dass Sie bereits eine Antwort eingereicht haben, als ich meine gesendet habe.
Neop
1
@Neop Nun, ich wusste nicht, dass du das weglassen könntest, int bis ich sah, dass es dir so gut geht!
Weizen-Assistent
2
Nicht C++nur der g ++ - Dialekt: C ++ verbietet das Aufrufen von main; C ++ erfordert eine int main...Deklaration. Aber die Lösung ist immer noch ordentlich :-)
Martin Ba
1
Tatsächlich verbietet C ++ das Aufrufen main.
R ..
9

JAVA, 81 79 78 Bytes

JAVA (HotSpot) 71 70 Bytes

Zum Zeitpunkt meiner Veröffentlichung kürzer als andere Java-Antworten (81, später 79 Byte):

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

Wie von @Olivier Grégoire vorgeschlagen, kann ein weiteres Byte gespeichert werden:

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

Das x+=x.intern()Inkrementieren als for-Schleife würde nichts nützen, da zum Beenden der for-Anweisung immer noch ein Semikolon erforderlich ist.

Wie von @ETHproductions vorgeschlagen, x+=xfunktioniert auch nur die Verwendung von :

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

Was auch von @Olivier Grégoires Tipp profitieren kann:

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

Meine einzigen Bedenken dabei sind, dass die Zuweisung von Daten auf dem Heap nicht garantiert ist , da eine effiziente JVM leicht erkennen kann, dass sie xder lokalen Funktion niemals entgeht. Die Verwendung von intern()vermeidet dieses Problem, da internierte Zeichenfolgen letztendlich in einem statischen Feld gespeichert werden. Allerdings generiert HotSpot einen OutOfMemoryErrorCode für diesen Code. Ich denke, das ist in Ordnung.

Update: @Olivier Gregoire wies auch darauf hin, dass der x+=xCode ausgeführt werden kann, StringIndexOutOfBoundsExceptionanstatt OOMwenn viel Speicher verfügbar ist. Dies liegt daran, dass Java den 32-Bit- intTyp verwendet, um Arrays zu indizieren (und Strings sind nur Arrays von char). Dies hat keine Auswirkung auf die x+=x.intern()Lösung, da der für letzteres erforderliche Speicher in der Länge der Zeichenfolge quadratisch ist und daher auf die Größenordnung von 2 ^ 62 zugewiesenen Bytes skaliert werden sollte.

DepressedDaniel
quelle
Willkommen bei PPCG! Ich kenne Java nicht sehr gut. Was würde passieren, wenn Sie es einfach tun würden x+=x;?
ETHproductions
Sie können ein Semikolon abschneiden, indem Sie x+=x.intern()das letzte Semikolon der for-Schleife
masterX244
Gute Antwort. Ich wusste, dass es etwas mit Besaitung geben musste, internaber ich war ziemlich zufrieden mit Unsafe und stellte fest, dass ich aufgehört hatte zu suchen, haha. Ursprünglich gab diese Frage "Memory Leak" an, weshalb ich nicht einfach eine String Concat-Antwort gemacht habe.
Poke
Wenn Ihre Antwort von einer bestimmten Java-Implementierung abhängt und nicht unbedingt auf alle Java-Implementierungen übertragbar ist, können Sie die Informationen in den Titel einfügen (z # Java (HotSpot), 71 bytes. B. ). Auf diese Weise brauchen Sie sich keine Sorgen zu machen, dass die Lösung möglicherweise betrügt. implementierungsspezifische Programme sind nicht nur im Golfsport verbreitet, sondern auch in der gesamten Programmierwelt. Solange Sie sich dessen bewusst sind, was Sie tun, ist dies manchmal geeigneter als ein portables Programm für beispielsweise ein Einzelprogramm. off script.
1
Humm ... x+=x;erschöpft nicht die ganze Erinnerung. Mit 64 GB bekomme ich ein StringIndexOutOfBoundsException, kein OOM. Mit .intern()bekomme ich noch die OOM.
Olivier Grégoire
8

Perl 6 , 13 Bytes

@= eager 0..*

Erläuterung:

@ = Speichern Sie das Ergebnis in einem unbenannten Array

eager mach die folgende Liste eifrig

0 .. * unendlicher Bereich beginnend bei Null

Brad Gilbert b2gills
quelle
8

///, 7 Bytes

/a/aa/a

Ersetzen ständig amit aa, bis zum Überdruss.

steenbergh
quelle
12
*aad naauseum
timothymh
1
* ad nauseam=>aad naauseaam
Aaron
Was ist //a/? Das scheint für immer `` (nichts) durch zu ersetzen a, ist sich aber nicht sicher, ob dies genau spezifiziert ist.
Cedric Reichenbach
6

Python 3, 16 Bytes

i=9
while 1:i*=i

Dies liegt an der Tatsache, dass es in Python 3 keine Beschränkung für die Ganzzahlgröße gibt. Stattdessen können Ganzzahlen so viel Speicher belegen, wie das System verarbeiten kann (wenn etwas an meinem Verständnis davon nicht stimmt, korrigieren Sie mich).

künstlich
quelle
Der Titel impliziert, dass der Speicher gelöscht werden sollte. Dies führt jedoch nicht zu Speicherverlusten. Der Autor sollte das wohl klarstellen.
Weizen-Assistent
6

Rust, 46 Bytes

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

Beachten Sie etwas Interessantes an diesem Rust-Programm, bei dem Heap-Zuordnungen verloren gehen, bis der Speicher voll ist?

Das ist richtig, kein unsicherer Block. Rust garantiert die Speichersicherheit in sicherem Code (kein Lesen von nicht initialisierten Daten, kein Lesen nach "free", "double free" usw.), aber Speicherverluste gelten als absolut sicher. Es gibt sogar eine explizite Funktion, mit der der Compiler die RAII-Bereinigung von Out-of-Scope-Variablen vergisst, die ich hier verwende.

Harald Korneliussen
quelle
6

TI-83 Hex Assembly, 7 Bytes

PROGRAM:M
:AsmPrgm
:EF6A4E
:C3959D
:C9

Erstellt Appvars auf unbestimmte Zeit, bis ERR:MEMORYsie vom Betriebssystem ausgelöst werden. Laufen Sie mit Asm(prgmM). Ich zähle jedes Paar hexadezimaler Ziffern als ein Byte.

Harry
quelle
6

Python, 8 Bytes

2**9**99

Das OP hat die technische Funktionalität eines Programms zugelassen, das technisch nicht "für immer" ausgeführt wird, sondern mehr Arbeitsspeicher zuweist, als ein Computer möglicherweise handhaben könnte. Dies ist kein Googolplex (das wären 10**10**10011 Bytes), aber naiv ist Log Base 2 der Zahl

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

dh 10 ^ 94 Bits, um es darzustellen. WolframAlpha nennt das 10 ^ 76 größer als das tiefe Netz (bedenken Sie, dass es im Universum etwa 10 ^ 80 Atome gibt ).

Warum fragst du 2 statt 9? Es macht keinen großen Unterschied (die Verwendung von 9 würde die Anzahl der Bits nur um den Faktor 1 erhöhen log2(9) = 3.2, was den Exponenten nicht einmal ändert). Andererseits läuft das Programm mit 2 aber viel schneller, da die Berechnung einfacher ist. Dies bedeutet, dass der Speicher sofort voll ist, im Gegensatz zur 9-Version, die aufgrund der erforderlichen Berechnungen etwas länger dauert. Nicht notwendig, aber schön, wenn Sie dies "testen" möchten (was ich getan habe).

Asmeurer
quelle
5

Gelee , 3 2 Bytes

-1 Byte dank Dennis ( Wwraps)

Eine Verknüpfung (dh Funktion oder Methode), die auch als vollständiges Programm funktioniert und deren Eingabe rekursiv in eine Liste einschließt.

Die Eingabe beginnt mit Null, sodass der erste Durchgang die Liste erstellt. [0]
Der zweite Durchgang macht dies. [[0]]
Der dritte Durchgang macht dies [[[0]]]
und so weiter.


Vorherige 3 Bytes, die viel schneller lecken:

;Ẇß

Verkettet rekursiv alle nicht leeren zusammenhängenden Unterlisten seiner Eingabe mit seiner Eingabe.
[0]-> [0,[0]]-> [0,[0],[0],[[0]],[0,[0]]]und so weiter ...

Jonathan Allan
quelle
Wenn ich die Regeln richtig verstehe, ‘ßsollte das reichen.
Dennis
Wird dadurch wirklich "kontinuierlich Speicher zugewiesen" (wenn man bedenkt, dass Python die Zuweisung für kleine Ints konstant hält)?
Jonathan Allan
1
Fair genug. sollte aber trotzdem passen.
Dennis
5

Java 7, 106 Bytes

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

Weniger Golf

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

Die finalizeMethode wird vom Garbage Collector für ein Objekt aufgerufen, wenn die Garbage Collection feststellt, dass keine weiteren Verweise auf das Objekt vorhanden sind. Ich habe diese Methode einfach neu definiert, um eine Endlosschleife zu erstellen, damit der Garbage Collector den Speicher nie freigibt. In der mainSchleife erstelle ich neue Objekte, die niemals bereinigt werden, so dass letztendlich der gesamte verfügbare Speicher belegt wird.

Java 7 (lustige Alternative), 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);}}

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

Dies ist ein Spaß mehr als alles andere. In dieser Antwort wird die UnsafeSun-Bibliothek verwendet, bei der es sich um eine nicht dokumentierte interne API handelt. Möglicherweise müssen Sie Ihre Compilereinstellungen ändern, um eingeschränkte APIs zuzulassen. Unsafe.allocateMemoryWeist eine festgelegte Anzahl von Bytes zu (ohne Begrenzungsüberprüfung), die sich nicht auf dem Heap und nicht in der Garbage Collector-Verwaltung von Java befinden, sodass dieser Speicher so lange erhalten bleibt, bis Sie einen Aufruf Unsafe.freeMemorytätigen oder bis der JVM-Speicher voll ist.

Sack
quelle
1
Ich habe mich gefragt, ob ich Java hier sehen würde.
Magic Octopus Urn
Funktioniert der erste nicht nur, wenn der Garbage Collector in einem separaten Thread ausgeführt wird?
tbodt
@tbodt ja, aber ich glaube nicht, dass dies jemals nicht der Fall ist. Die Speicherbereinigung erfolgt in einem Daemon-Thread namens Garbage Collector
Poke
@Poke ist das garantiert? wenn nicht, ist die Antwort noch in Ordnung, aber Sie sollten klarstellen, dass es nur funktioniert, wenn der Garbage Collector in einem eigenen Thread ausgeführt wird
bis zum
@tbodt Ich denke schon , aber ich bin ehrlich gesagt nicht sicher.
Poke
5

Haskell, 24 Bytes

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

Das Hauptproblem in Haskell ist es, die Faulheit zu besiegen. mainmuss einen IOTyp haben, also main=f 9würde es nicht funktionieren , einfach anzurufen . Mit wird main=pure(f 9)der Typ von f 9auf einen IOTyp angehoben. Verwendung von Konstrukten jedoch wie main=pure 9nicht alles tun, die 9zurückgegeben oder nirgends angezeigt , sondern einfach verworfen, so dass keine Notwendigkeit besteht, das Argument zu bewerten pure, daher main=pure(f 9)verursacht keine Speicher als zugeteilt werden fnicht genannt. Um die Auswertung zu erzwingen, $!existiert der Operator. Es wendet einfach eine Funktion auf ein Argument an, wertet das Argument jedoch zuerst aus. Durch die Verwendung von main=pure$!f 9Auswertungen wird falso kontinuierlich mehr Speicher zugewiesen.

Laikoni
quelle
Beim Kompilieren erkennt die Laufzeit die Schleife und bricht die Ausführung ab
Angs
@Angs Ich habe mit ghc unter Windows kompiliert und es ordnet immer wieder Speicher zu ... Ich habe es bei 3 GB gestoppt.
Laikoni
Funktioniert f x=f xauch mit, oder? (
2
@wchargin Ich glaube nicht, f x=f xerzeugt eine Endlosschleife, ohne jedoch neuen Speicher zuzuweisen .
Laikoni
Schön, dass das Gedächtnis durch die Bignum-Berechnungen kaputt geht! f!x=x*f(x*x)sollte es optimierungssicher machen.
Will Ness
5

Gleichstrom, 7 Bytes

[ddx]dx

[ddx]Drückt einen String mit "ddx" auf den Stack. dxdupliziert es und führt es dann als Code aus (wobei eine Kopie auf dem Stapel verbleibt). Bei der Ausführung werden zwei Duplikate erstellt und eines ausgeführt, wobei jedes Mal eine weitere Kopie auf dem Stapel verbleibt.

faubi
quelle
Warten Sie, damit dies den Speicher exponentiell reservieren würde, wenn er parallel ausgeführt werden könnte.
HyperNeutrino
5

Haskell (mit ghc 8.0.1), 11 Bytes

m@main=m>>m

Non-Tail-Rekursion. mainruft sich selbst an und dann wieder selbst.

nimi
quelle
Wird dies auf dem Heap oder dem Stack zugewiesen? (Ich kann es auch glauben; es kann durchaus vom Haskell-Compiler abhängen,
1
@ ais523: es kommt darauf an. Haskell hat keine Aufrufliste . Das Laufzeitsystem RTS verfügt über einen Speicherbereich für den Pattern Matching, der auch als "Stack" bezeichnet wird. Dieser Stapel wird auf dem Heap zugeordnet. Ehrlich gesagt, ich weiß nicht, was hier vor sich geht, da das Programm mit Stack space overflow: current size 33624 bytes.33 KB im Gegensatz zu den 6 GB des Gesamtspeichers, die das Betriebssystem meldet, ziemlich niedrig erscheint.
nimi
1
@ ais523: Es scheint einen Fehler in den Speicherinformationen der ghc-Fehlermeldung zu geben, daher ist es schwierig zu sagen, was genau passiert.
Nimi
Auf GHC 7.10.3 unter Ubuntu kompiliert, scheint dies eine konstante Menge an Speicher zu beanspruchen, selbst wenn Optimierungen deaktiviert sind
Angs
@Angs: hmm, ich benutze ghc 8.0.1 unter MacOS. Ich bearbeite das in.
nimi
5

C (Linux), 23 Bytes

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

sbrk()Schritte der Oberseite des Datensegmentes durch die gegebene Anzahl von Bytes, wodurch wirksam die Größe des Speichers zu dem Programm zugeordnet Erhöhung - zumindest in dem ausgewiesenen VIRTBereich topausgegeben. Dies funktioniert nur unter Linux - die MacOS-Implementierung ist anscheinend eine Emulation, die nur die Zuweisung von bis zu 4 MB ermöglicht.


Also eine etwas allgemeinere Antwort:

C 25 Bytes

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

Ich habe es auf dem macOS Activity Monitor gesehen. Es ging den ganzen Weg bis zu etwa 48 GB, dann erhielt der Prozess schließlich ein SIGKILL-Signal. FWIW mein MacBook Pro hat 16 GB. Der größte Teil des verwendeten Speichers wurde als komprimiert gemeldet.

Beachten Sie, dass für die Frage effektiv jede Zuordnung geschrieben werden muss, was hier nicht explizit geschieht. Es ist jedoch wichtig zu beachten, dass für jeden malloc(9)Aufruf nicht nur die 9 vom Benutzer angeforderten Bytes zugewiesen werden. Für jeden zugewiesenen Block gibt es einen Malloc-Header, der auch von irgendwo auf dem Heap zugewiesen wird, auf den die malloc()Interna notwendigerweise schreiben .

Digitales Trauma
quelle
Mit malloc schreiben Sie nicht direkt in den Speicher, da malloc nichts initialisiert. Der Speicher wird nur zugewiesen, weil malloc internen Speicher für die Speicherverwaltung benötigt. Die Antwort ist also nicht wirklich Standard, aber ich denke, sie funktioniert trotzdem überall.
Antzi
@Antzi Ja. Ich denke jedoch, dass dies immer noch funktioniert, da, obwohl der Benutzerspeicher möglicherweise nicht zugewiesen wird, bevor er beschrieben wird, jeder malloc()ed-Block immer noch seinen eigenen zugewiesenen realen Speicherplatz haben muss. Dies funktioniert unter MacOS und Ubuntu.
Digitales Trauma
Die Bedingung in der Frage, in die jede Seite geschrieben wird, ist ziemlich bedeutungslos; Selbst wenn Sie davon ausgehen möchten, dass ein Betriebssystem keine ordnungsgemäße Festschreibungsabrechnung durchführt, ist unabhängig von den Implementierungsdetails notwendigerweise ein Buchhaltungsaufwand ungleich Null pro Zuordnung erforderlich. Unabhängig davon, ob es an die Zuordnung angrenzt (wodurch Seiten berührt werden) oder nicht, verbraucht es möglicherweise beliebig viel Speicher für die Buchhaltung mit (notwendigerweise) Daten ungleich Null.
R ..
Sie könnten es um ein Byte verkleinern main(){main(malloc(9));}, aber um einen Stapelüberlauf zu vermeiden, ist eine Tail-Call-Optimierung erforderlich, und gcc scheint dies nicht zu wollen main...
R ..
Wenn Sie malloc (9) durch calloc (9,9) ersetzen, wird genügend Speicher für 9 Instanzen eines 9-Byte-Blocks reserviert (also zwischen 81 und 144 Byte, abhängig von der Ausrichtung. Noch wichtiger ist jedoch, dass calloc ( ) wird den Speicherblock mit Null füllen, wodurch das zugrunde liegende Betriebssystem gezwungen wird, ihm Speicher zuzuweisen.
CSM
5

Perl, 4 Bytes

do$0

Führt sich selbst im aktuellen Interpreter aus. Nach Abschluss der Ausführung kehrt die Ausführung zum aufrufenden Skript zurück, für das ein Aufrufstapel erforderlich ist.

primo
quelle
Nett und kurz, obwohl es nicht so schnell Speicher verschwendet wie meins.
BenGoldberg
4

Schläger, 13 Bytes

(let l()(l)1)

Ich bin nicht ganz sicher, ob meine Antwort unter diese Frage fällt. Bitte lassen Sie mich wissen, ob ich diese Antwort entfernen soll.

Winny
quelle
Kannst du erklären, wie es funktioniert?
1.
1
Oh, also definiert es sich lals eine Funktion, die Non-Tailcall-Rekursion ausführt. Ich würde sagen, es zählt.
tbodt
@ Tbodt ja, Sie haben Recht auf das Geld
Winny
4

JavaScript 22 21 17 16 15 Bytes

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

4 Bytes wurden gespeichert, indem die Liste in eine andere Liste wie in der @ Jonathan Allan's Jelly-Antwort eingeschlossen wurde.

1 Byte dank @ETHProductions eingespart

Alternative Lösung 15 Bytes (funktioniert nur mit richtigen Tail Calls)

f=a=>f([a]);f()
Lmis
quelle
1
Könnten Sie das bei Ihrem zweiten Beispiel mit ES6 nicht einfach tun f=_=>f();f()? 12 Bytes
gebissen
@bitten Ich bin mir nicht sicher. Wenn es darauf ankommt, den Call-Stack zu sprengen, dann ist dieser ohne die richtigen Tail-Calls der richtige Weg. Ich glaube nicht, dass bei TCO Speicherlecks auftreten würden, oder?
Lmis
beide blasen den callstack für mich . Ich bin nicht wirklich vertraut mit Tail Calls, daher kann ich das nicht kommentieren.
Gebissen
1
ah ich verstehe, ich war mir nicht sicher, wie deine erinnerung verloren ging
gebissen
1
Sie könnten entfernen a=0. Die erste Iteration würde ergebena=[undefined]
Florent
4

Ruby, 11 Bytes

loop{$*<<9}

Hält drückt 9auf $*zunächst die ein Array ist die Befehlszeilenargumente zum Ruby - Prozess zu halten.

daniero
quelle
4

05AB1E , 2 Bytes

[A

Probieren Sie es online! Werde einfach abcdefghijklmnopqrstuvwyxzfür die Ewigkeit weiter auf den Stapel schieben .

Alle möglichen 2-Byte-Lösungen:

[  # 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.
Magische Kraken-Urne
quelle
Sehr ausführlich! Nett.
timothymh
3

Python, 35 Bytes

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

a wird nie veröffentlicht und wird nur größer, bis Sie ein treffen MemoryError

Sie können die Ausführung in Python Tutor anzeigen .

Noelkd
quelle
1
Schaffst du das a+=a,?
Cyoce
Keine Notwendigkeit für eine Funktion, hier ist mein Golf davon
FlipTack
@ Flp.Tkc Die Frage wurde geändert, nachdem ich diese Antwort geschrieben hatte. Ich hätte getan, was Sie getan haben (+ - ein paar Zeichen), wenn es in seinem aktuellen Format wäre.
Noelkd
3

TI-BASIC, 8

:Lbl A
:While 1
:Goto A

(alle 1-Byte-Token und zwei Zeilenumbrüche)

Dies führt zu einem kontinuierlichen Speicherverlust, da ein strukturierter Steuerungsfluss, wie er beispielsweise Whiledurch ein erwartet wird, geschlossen wird Endund etwas auf den Stapel schiebt (nicht den Betriebssystemstapel, einen separaten Stapel im Heapspeicher), um den Überblick zu behalten. Aber hier verlassen wir Gotodie Schleife (also wird no Endausgeführt, um das Ding vom Stapel zu entfernen), das Whilewird erneut gesehen, das Ding wird erneut geschoben usw. Also schiebt es sie einfach so lange, bis Sie es bekommenERR:MEMORY

Harold
quelle