Napisz program, który działa wiecznie i przydziela coraz więcej pamięci na stercie, im dłużej działa, przynajmniej dopóki nie osiągniesz limitu systemu operacyjnego na ilość pamięci, którą można przydzielić.
Wiele jąder nie rezerwuje faktycznie przydzielonej pamięci, dopóki jej nie wykorzystasz, więc jeśli twój program jest w C lub innym języku niskiego poziomu, musisz upewnić się, że napisałeś coś na każdej stronie. Jeśli używasz tłumaczonego języka, prawdopodobnie nie będziesz musiał się tym martwić.
Najkrótszy kod wygrywa.
(reduce conj [] (range))
(Clojure) osiąga 737 MB, po czym przestaje rosnąć. Idk, jak to nie idzie w górę. „Myśli”, że chcę wydrukować całą listę na końcu, więc nie powinno się jej wyrzucać. Bardzo frustrujące.Odpowiedzi:
Funge-98 (
cfunge
), 1 bajtOpublikowałbym to wcześniej, ale postanowiłem to przetestować i zajęło mi trochę czasu, aby przywrócić komputer do stanu używalności.
cfunge
przechowuje stos Funge na stercie systemu operacyjnego (który można łatwo zweryfikować, uruchamiając program z małym limitem pamięci, co powinienem był zrobić wcześniej!), a więc nieskończenie rosnący stos (jak w przypadku tego programu, który po prostu naciska9
wielokrotnie; Domyślnie zawijanie programów od końca linii z powrotem do początku) przydzieli pamięć na zawsze. Ten program prawdopodobnie działa również w niektórych implementacjach Befunge-93.Bardziej interesujące:
To był mój pierwszy pomysł i jest to nieskończona alokacja, która nie opiera się na stosie Funge (chociaż wysadza też stos Funge). Na początek
"
polecenie wypycha kopię pozostałej części programu na stos (jest to ciąg znaków, a program jest zawijany, więc cytat zamykający służy również jako cytat otwarty). NastępnieN
odbija się (domyślnie nie ma znaczenia), co powoduje, że program działa wstecz. Do"
ponownie biegnie i pcha program na stosie - okrągłe ten czas w inny sposób, przy czymN
na wierzchu stosu - to program otacza, ładuje bibliotekę o nazwie 4-literowego (4(
, aNULL
biblioteka jest częściącfunge
standardowa biblioteka).NULL
określa wszystkie wielkie litery do odzwierciedlenia, więcL
odzwierciedla,#
pomija ładowanie biblioteki w drodze powrotnej,4
wypycha śmieci, które nas nie obchodzą, do stosu, a cały program powtarza się od początku. Biorąc pod uwagę, że wielokrotne ładowanie biblioteki ma efekt i wymaga, aby lista poleceń biblioteki była przechowywana raz dla każdej kopii biblioteki (wynika to z semantyki Funge-98), wycieka ona z pamięci przez pamięć bez stosu (która jest alternatywna metoda definiowania „sterty” w odniesieniu do języka, a nie systemu operacyjnego).źródło
0
możliwych; możliwe jest, że implementacja Funge lub system operacyjny mogą znaleźć sposób na zoptymalizowanie tego, biorąc pod uwagę, że pamięć jest już pełna zer). Właśnie wybrałem9
arbitralnie.Brainfuck, 5 bajtów
Wymaga to interpretera, który nie ma ograniczenia długości taśmy.
źródło
Bash + coreutils, 5
lub
Ruby, 5
yes
produkuje nieskończoną moc wyjściową. Wstawienieyes
backticksa każe powłoce przechwycić wszystkie dane wyjściowe, a następnie wykonać je jako polecenie. Bash będzie kontynuował przydzielanie pamięci dla tego niekończącego się ciągu, aż skończy się stos. Oczywiście wynikowy wynik byłby niepoprawnym poleceniem, ale powinniśmy zabraknąć pamięci, zanim to nastąpi.Dzięki @GB za wskazanie, że jest to również poliglot w rubinie.
źródło
Python, 16 bajtów
Utrzymuje zagnieżdżanie,
a
aż do osiągnięcia błędu:Pierwsze kilka iteracji (jako krotki) wygląda następująco:
i tak dalej i tak dalej.
źródło
> <> (Ryba), 1 bajt
Wypróbuj tutaj!
0
można faktycznie zastąpić dowolną liczbą szesnastkową 1-f.Wyjaśnienie
0
in> <> po prostu tworzy szafkę kodową 1x1, w której ryby mogą pływać. Ciągle dodaje0
stos do stosu, pływa w prawo, co powoduje pętlę do tyłu0
, dodając go ponownie do stosu. Trwa to wiecznie.źródło
.
(lub dowolnego innego niż biały znak), aby przesunąć0
linię wykonania.0000000...
jako literał o pojedynczej liczbie całkowitej, a ciąg znaków, który tworzy, zajmuje więcej pamięci. Program, który działa tak jak ten programa
(przesuwa 10 w nieskończoność).Java 101 bajtów
Łapanie programu głównego w niekończącej się pętli po utworzeniu i wyrzuceniu obiektu. Wyrzucanie elementów bezużytecznych wykonuje wyciek, tworząc 2 obiekty dla każdego usuniętego
źródło
Perl, 12 bajtów
W perlu
x
operator z ciągiem po lewej stronie i liczbą po prawej tworzy ciąg powtarzający się. Tak"abc" x 3
ocenia do"abcabcabc"
.x=
Operator mutuje lewy argument, zastępując zawartość zmiennej z lewej z wynikiem powtarzając jego zawartość tyle razy, ile jego prawej stronie wskazuje.Perl ma pewną liczbę dziwnie nazwanych wbudowanych zmiennych, z których jedną jest
$"
, której początkową wartością jest pojedyncza spacja.redo
Operator przeskakuje do początku załączania{}
.Przy pierwszym wykonaniu
x=
operator zmienia wartość$"
z" "
„na”" "
, czyli 9 spacji.Przy drugim wykonaniu
x=
operator zmienia wartość$"
na" "
, czyli 81 spacji.Za trzecim razem
$"
staje się ciągiem spacji o długości 729 bajtów.Myślę, że widać, dokąd to zmierza :).
źródło
$_.=7
w swojej pętli, ale zdałem sobie sprawę, że jeśli mógłbymx=
go użyć , zabrakłoby pamięci znacznie szybciej, a następnie pobiegłem,perldoc perlvar
aby wybrać coś odpowiedniego.{$^O++;redo}
jest o jeden bajt krótszy, gdy^O
jest o jedenchr(15)
bajt. Chociaż marnuje pamięć o DUŻO wolniej - w systemie Windows wymagane są iteracje 1000000000, aby zmarnować jeden bajt. Działa na każdym systemie operacyjnym, którego nazwa zaczyna się na łaciński.sed, 5 bajtów
Grał w golfa
Użycie (wystarczy dowolne wejście)
Wyjaśniono
Zrzut ekranu
Wypróbuj online!
źródło
Haskell,
2319 bajtówWydrukuj sumę nieskończonej listy
źródło
sum
definiuje się jakofoldl (+) 0
i co zatrzymać analizę rygorystyczności, aby rozpocząć, aby zapobiec wydmuchiwaniu? Czy uruchomiłeś go skompilowany z optymalizacjami?sum
nie będzie wiedział z góry, że lista jest nieskończona iprint
sumę należy najpierw ocenić. I tak, skompilowałem to z optymalizacjamiInteger
uderz , że z powodu domyślnej liczby są nieograniczone, a pamięć zajęta przez bieżący wynik bignum rzeczywiście by się powiększyła.sum xs = foldl (+) 0 xs
mogą przebiegać w trybie ciągłego stosu, tak jak w przypadku każdej pętli imperatywnej .foldl' (+) 0 xs
na pewno będzie. Tak więc jedyną rzeczą przydzielającą pamięć na pewno jest tymczasowy wynik bignum.C ++ (przy użyciu kompilatora g ++),
272315 bajtówDzięki Neop za pomoc w usunięciu 4 bajtów
To rozwiązanie tak naprawdę nie przecieka pamięci, ponieważ alokuje wszystko na stosie, a zatem powoduje przepełnienie stosu. Jest po prostu nieskończenie rekurencyjny. Każda rekurencja powoduje, że część pamięci zostaje przydzielona do momentu przepełnienia stosu.
Alternatywne rozwiązanie
To rozwiązanie przecieka pamięć.
Wyjście Valgrind
Jest to wyjście Valgrind po zakończeniu programu na kilka sekund przed uruchomieniem. Widać, że z pewnością przecieka pamięć.
źródło
int
dopóki nie zobaczyłem twoich podziękowań!C++
, tylko jego dialekt g ++: C ++ zabrania wywoływania main; C ++ wymagaint main...
deklaracji. Ale rozwiązanie jest nadal fajne :-)main
.JAWA,
817978 bajtówJAVA (HotSpot)
7170 bajtówKrótszy niż inne odpowiedzi Java w momencie, gdy publikowałem (81, później 79 bajtów):
Jak sugeruje @Olivier Grégoire, można zapisać kolejny bajt:
Umieszczenie
x+=x.intern()
jako przyrost pętli for nic by nie pomogło, ponieważ średnik jest nadal wymagany do zakończenia instrukcji for.Jak sugeruje @ETHproductions, samo użycie
x+=x
również działa:Które mogą również skorzystać z porady @Olivier Grégoire:
Moje jedyne wątpliwości co do tego polega na tym, że nie ma gwarancji przydzielenia danych na stercie , ponieważ wydajna maszyna JVM może łatwo zdać sobie sprawę, że
x
nigdy nie ucieka od funkcji lokalnej. Użycieintern()
pozwala uniknąć tego problemu, ponieważ internowane łańcuchy ostatecznie są przechowywane w polu statycznym. Jednak HotSpot generujeOutOfMemoryError
dla tego kodu, więc myślę, że jest w porządku.Aktualizacja: @Olivier Gregoire wskazał również, że
x+=x
kod może się uruchamiać,StringIndexOutOfBoundsException
a nieOOM
kiedy jest dużo pamięci. Wynika to z faktu, że Java używa typu 32-bitowegoint
do indeksowania tablic (a ciągi to tylko tablicechar
). Nie wpływa to nax+=x.intern()
rozwiązanie, ponieważ pamięć wymagana dla tego drugiego jest kwadratowa pod względem długości łańcucha i dlatego powinna być skalowana w górę do 2 ^ 62 przydzielonych bajtów.źródło
x+=x;
?x+=x.intern()
ostatni średnik pętli forintern
ale byłem całkiem zadowolony z Niebezpiecznych i doszedłem do wniosku, że przestałem szukać, haha. Pierwotnie to pytanie określało „wyciek pamięci”, dlatego właśnie nie zrobiłem odpowiedzi konkatkującej ciąg znaków.# Java (HotSpot), 71 bytes
.). W ten sposób nie musisz martwić się o rozwiązanie potencjalnie oszukiwające; Programy specyficzne dla implementacji są powszechne nie tylko w golfie, ale także w szerszym świecie programowania, i pod warunkiem, że wiesz, co robisz, może być czasem bardziej odpowiednie niż program przenośny dla, powiedzmy, jednego poza skryptem.x+=x;
nie wyczerpuje całej pamięci. Z 64 GB dostajęStringIndexOutOfBoundsException
OOM, a nie OOM. Z.intern()
nadal dostaję OOM.Perl 6 , 13 bajtów
Wyjaśnienie:
@ =
zapisz wynik w nienazwanej tablicyeager
spraw, aby poniższa lista była chętna0 .. *
nieskończony zakres, zaczynając od zeraźródło
///, 7 bajtów
Stale wymieniać
a
zaa
ad nauseum.źródło
aad naauseum
ad nauseam
=>aad naauseaam
//a/
? To wydaje się na zawsze zastępować `` (nic)a
, ale nie jestem pewien, czy jest to dokładnie określone.Python 3, 16 bajtów
Wynika to z faktu, że w Pythonie 3 nie ma ograniczenia rozmiaru liczb całkowitych; zamiast tego liczby całkowite mogą zająć tyle pamięci, ile system może obsłużyć (jeśli coś w moim rozumieniu tego jest błędne, popraw mnie).
źródło
Rdza, 46 bajtów
Zauważasz coś interesującego w tym programie Rust, przecieki przydziałów sterty aż do braku pamięci?
Zgadza się, nie ma niebezpiecznego bloku. Rdza gwarantuje bezpieczeństwo pamięci w bezpiecznym kodzie (brak odczytu niezainicjowanych danych, odczyt po wolnym, podwójnym wolnym itd.), Ale wycieki pamięci są uważane za całkowicie bezpieczne. Istnieje nawet wyraźna funkcja pozwalająca kompilatorowi zapomnieć o czyszczeniu RAII zmiennych poza zakresem, których tutaj używam.
źródło
Zestaw sześciokątny TI-83, 7 bajtów
Tworzy appvars w nieskończoność, dopóki system
ERR:MEMORY
operacyjny nie wyrzuci znaku an . Uruchom zAsm(prgmM)
. Liczę każdą parę cyfr szesnastkowych jako jeden bajt.źródło
Python, 8 bajtów
OP pozwoliło na technicyzacji programu, który nie technicznie prowadzony „na zawsze”, ale przydziela więcej pamięci niż jakikolwiek komputer mógłby obsłużyć. To nie jest całkiem googolplex (to byłoby
10**10**100
11 bajtów), ale naiwnie, podstawa logarytmiczna 2 liczby totj. 10 ^ 94 bitów do jego przedstawienia. WolframAlpha twierdzi, że jest o 10 ^ 76 większy niż głęboka sieć (pamiętaj, że we wszechświecie jest około 10 ^ 80 atomów ).
Dlaczego pytasz 2 zamiast 9? Nie robi to dużej różnicy (użycie 9 zwiększyłoby tylko liczbę bitów o współczynnik
log2(9) = 3.2
, co nawet nie zmienia wykładnika). Ale z drugiej strony program działa znacznie szybciej z 2, ponieważ obliczenia są prostsze. Oznacza to, że natychmiast zapełnia pamięć, w przeciwieństwie do wersji 9, która zajmuje nieco dłużej ze względu na wymagane obliczenia. Nie jest to konieczne, ale miło, jeśli chcesz to „przetestować” (co zrobiłem).źródło
Galaretka ,
32 bajty-1 bajt dzięki Dennisowi (
W
okłady)Link (tj. Funkcja lub metoda), który działa również jako pełny program, który rekurencyjnie zawija swoje dane wejściowe na listę.
Dane wejściowe zaczynają się od zera, więc pierwsze przejście tworzy listę
[0]
Drugie przejście następnie powoduje, że
[[0]]
Trzecie przejście następnie czyni to
[[[0]]]
i tak dalej ...
Poprzednie 3 bajty, które przeciekają znacznie szybciej:
rekurencyjnie łączy wszystkie niepuste ciągłe podlisty swoich danych wejściowych z danymi wejściowymi.
[0]
->[0,[0]]
->[0,[0],[0],[[0]],[0,[0]]]
i tak dalej ...źródło
‘ß
powinno być dużo.Wß
nadal powinien pasować do rachunku.Java 7, 106 bajtów
Mniej golfa
finalize
Wywoływana jest metoda na obiekcie przez śmieciarza, gdy stwierdzi, że zbieranie śmieci nie ma już odniesienia do obiektu. Po prostu przedefiniowałem tę metodę, aby zapętlała się w nieskończoność, aby śmieciarz nigdy nie zwalnia pamięci. Wmain
pętli tworzę nowe obiekty, które nigdy nie zostaną oczyszczone, więc ostatecznie zużyje całą dostępną pamięć.Java 7 (fajna alternatywa), 216 bajtów
Mniej golfa
To jest zabawne bardziej niż cokolwiek innego. Ta odpowiedź korzysta z
Unsafe
biblioteki Sun, która jest nieudokumentowanym wewnętrznym interfejsem API. Może być konieczna zmiana ustawień kompilatora, aby umożliwić ograniczone interfejsy API.Unsafe.allocateMemory
alokuje określoną liczbę bajtów (bez sprawdzania granic), która nie znajduje się na stercie i nie jest zarządzana przez moduł zbierający elementy bezużyteczne Javy, więc ta pamięć pozostanie do czasu wywołaniaUnsafe.freeMemory
lub do wyczerpania się pamięci JVM.źródło
Haskell, 24 bajty
Głównym problemem w Haskell jest pokonanie lenistwa.
main
musi mieć jakiśIO
typ, więc zwykłe dzwonieniemain=f 9
nie zadziała. Użyciemain=pure(f 9)
podnosi typf 9
doIO
typu. Jednak używanie konstrukcji typumain=pure 9
nic nie robi,9
jest zwracane lub wyświetlane nigdzie, ale po prostu odrzucane, więc nie trzeba oceniać argumentupure
, a zatemmain=pure(f 9)
nie powoduje przydzielania pamięci, ponieważf
nie jest wywoływana. Aby wymusić ocenę,$!
operator istnieje. Po prostu stosuje funkcję do argumentu, ale najpierw ocenia argument. Tak więc używaniemain=pure$!f 9
ewaluuje,f
a zatem stale przydziela więcej pamięci.źródło
f x=f x
też działa, prawda? (−2 bajty)f x=f x
tworzy nieskończoną pętlę, ale bez przydzielania nowej pamięci.f!x=x*f(x*x)
powinien być odporny na optymalizacje.dc, 7 bajtów
[ddx]
wypycha na stos ciąg zawierający „ddx”.dx
duplikuje go, a następnie wykonuje jako kod (pozostawiając jedną kopię na stosie). Po wykonaniu tworzy dwa duplikaty, a następnie wykonuje jeden, pozostawiając za każdym razem jeszcze jedną kopię na stosie.źródło
Haskell (przy użyciu ghc 8.0.1), 11 bajtów
Rekurencja bez ogona.
main
wywołuje siebie, a potem siebie ponownie.źródło
Stack space overflow: current size 33624 bytes.
33k, wydaje się dość niski w przeciwieństwie do 6G całkowitej pamięci zgłaszanej przez system operacyjny.C (linux), 23 bajty
sbrk()
zwiększa górną część segmentu danych o podaną liczbę bajtów, tym samym skutecznie zwiększając ilość pamięci przydzielonej programowi - przynajmniej tak, jak podano wVIRT
polu danychtop
wyjściowych. Działa to tylko w systemie Linux - implementacja macOS jest najwyraźniej emulacją, która pozwala na alokację do 4 MB.Więc nieco bardziej ogólna odpowiedź:
C, 25 bajtów
Oglądałem to na monitorze aktywności macOS. Poszło aż do około 48 GB, a następnie proces otrzymał sygnał SIGKILL. FWIW mój MacBook Pro ma 16 GB. Większość użytej pamięci zgłoszono jako skompresowaną.
Pamiętaj, że pytanie skutecznie wymaga zapisania każdego przydziału, co nie zdarza się tutaj wyraźnie. Należy jednak pamiętać, że dla każdego
malloc(9)
połączenia przydzielane są nie tylko 9 bajtów żądanych przez użytkownika. Dla każdego przydzielonego bloku będzie nagłówek malloc, który jest również przydzielany gdzieś na stercie, do którego koniecznie zapisują elementymalloc()
wewnętrzne.źródło
malloc()
blok ed musi nadal mieć swoje prawdziwe przydzielone miejsce. Działa to na macOS i Ubuntu.main(){main(malloc(9));}
, ale aby nie przepełniać stosu, wymaga optymalizacji wywołania ogona, a gcc nie chce tego robić w dniumain
...Perl, 4 bajty
Wykonuje się w bieżącym tłumaczu. Po zakończeniu wykonanie powraca do skryptu wywołującego, który wymaga stosu wywołań.
źródło
Rakieta, 13 bajtów
Nie jestem całkowicie pewien, czy moja odpowiedź mieści się w tym pytaniu. Daj mi znać, czy powinienem usunąć tę odpowiedź.
źródło
l
jako funkcję, która wykonuje rekurencję bez wywołania ogona. powiedziałbym, że to się liczy.JavaScript
2221171615 bajtówZaoszczędzono 4 bajty, zawijając listę na inną listę, jak w odpowiedzi Jelly'ego Allana na galaretkę.
Zaoszczędzono 1 bajt dzięki @ETHProductions
Alternatywne rozwiązanie 15 bajtów (działa tylko z odpowiednimi wywołaniami ogona)
źródło
f=_=>f();f()
? 12 bajtówa=0
. Pierwsza iteracja spowodowałabya=[undefined]
Rubinowy, 11 bajtów
Naciska
9
na$*
, która jest tablicą początkowo przechowującą argumenty wiersza poleceń dla procesu Ruby.źródło
05AB1E , 2 bajty
Wypróbuj online! Będzie po prostu naciskać
abcdefghijklmnopqrstuvwyxz
na stos na wieczność.Wszystkie możliwe rozwiązania 2-bajtowe:
źródło
Python, 35 bajtów
a
nigdy nie jest wypuszczany i tylko staje się większy, dopóki nie trafiszMemoryError
Możesz zobaczyć wykonanie w Python Tutor .
źródło
a+=a,
?TI-BASIC, 8
(wszystkie 1-bajtowe tokeny i dwa znaki nowej linii)
Powoduje to ciągłe wycieki pamięci, ponieważ ustrukturyzowany przepływ sterowania, taki jak
While
przewidywane zamknięcie przezEnd
i, wypycha coś na stos (nie na stos operacyjny, oddzielny stos w pamięci stosu), aby to śledzić. Ale tutaj używamyGoto
do opuszczenia pętli (więc nieEnd
jest wykonywane żadne polecenie usunięcia rzeczy ze stosu), toWhile
jest ponownie widoczne, rzecz jest ponownie wypychana itp. Więc po prostu ją popycha, dopóki nie pojawi sięERR:MEMORY
źródło