Najkrótszy program, który stale przydziela pamięć

49

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.

tbodt
źródło
13
Czy przepełnienie stosu jest prawidłowym rozwiązaniem? Czy pamięć musi być wyciekła czy tylko przydzielona?
Wheat Wizard
1
@WheatWizard Pamięć nie musi być wyciekana, ale musi zostać przydzielona szybciej niż jest zwolniona.
tbodt
2
Raz, kiedy chcę, aby mój program zużywał nieskończoną pamięć, nie mogę tego zrobić. (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.
Carcigenicate
14
Uwaga do siebie: Zapisz kod przed testowaniem. Wprowadzenie wycieków
memów
1
Myślę, że powinieneś dodać kolejne wyzwanie golfowe, podobne, ale odrębne, wymagające, aby program zużywał pamięć szybciej niż liniowa funkcja czasu. W przypadku bieżącego wyzwania zapętlenie na zawsze i przydzielenie jednego bajtu powinno być w porządku. W przypadku nowego wyzwania byłoby to niewystarczające, ale zapętlenie na zawsze i podwojenie ilości pamięci używanej za każdym razem byłoby w porządku.
BenGoldberg,

Odpowiedzi:

46

Funge-98 ( cfunge), 1 bajt

9

Opublikowałbym to wcześniej, ale postanowiłem to przetestować i zajęło mi trochę czasu, aby przywrócić komputer do stanu używalności. cfungeprzechowuje 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 naciska 9wielokrotnie; 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:

"NULL #(4

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ępnie Nodbija 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 czym Nna wierzchu stosu - to program otacza, ładuje bibliotekę o nazwie 4-literowego ( 4(, a NULLbiblioteka jest częścią cfungestandardowa biblioteka). NULLokreśla wszystkie wielkie litery do odzwierciedlenia, więc Lodzwierciedla,#pomija ładowanie biblioteki w drodze powrotnej, 4wypycha ś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
2
Po prostu przyjmuję to ...
tbodt
Czy konieczne jest, aby liczba wynosiła 9? Czy to też zadziałałoby, gdyby było 5?
tbodt
Wszystko, co wypycha na stos, działa (z wyjątkiem 0moż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łem 9arbitralnie.
22
Nieakceptowalne, ponieważ chcę, aby moja reputacja wciąż wynosiła 666.
tbodt
7
@tbodt Nie jest to prawdziwy powód, aby nie akceptować. Jeśli chcesz, zadam -1 pytanie. Po zaakceptowaniu nadal będziesz mieć 703 (pamiętaj, że masz teraz 703, a nie 666).
NoOneIsHere
30

Brainfuck, 5 bajtów

+[>+]

Wymaga to interpretera, który nie ma ograniczenia długości taśmy.

vsz
źródło
2
Jestem prawie pewien, że to + [> +], bo inaczej po prostu zatrzyma się przy pierwszej iteracji. ;)
Pâris Douady
Masz rację, przepraszam za literówkę.
vsz
40
Jeden z rzadkich
momentów, w
@ Flp.Tkc Ale wciąż przegrywa. Może kiedyś wygra ...
NoOneIsHere
6
@SeeOneRhino: Już raz wygrał, pokonując wszystkie języki gry w golfa> codegolf.stackexchange.com/questions/8915/…
vsz
22

Bash + coreutils, 5

lub

Ruby, 5

`yes`

yesprodukuje nieskończoną moc wyjściową. Wstawienie yesbackticksa 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.

Cyfrowa trauma
źródło
7
Już miałem napisać to samo i nazwać to programem Ruby.
GB
1
i perl, tak myślę.
abligh,
18

Python, 16 bajtów

Utrzymuje zagnieżdżanie, aaż do osiągnięcia błędu:

a=0
while 1:a=a,

Pierwsze kilka iteracji (jako krotki) wygląda następująco:

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

i tak dalej i tak dalej.

FlipTack
źródło
18

> <> (Ryba), 1 bajt

0

Wypróbuj tutaj!

0 można faktycznie zastąpić dowolną liczbą szesnastkową 1-f.

Wyjaśnienie

0in> <> po prostu tworzy szafkę kodową 1x1, w której ryby mogą pływać. Ciągle dodaje 0stos do stosu, pływa w prawo, co powoduje pętlę do tyłu 0, dodając go ponownie do stosu. Trwa to wiecznie.

redstarcoder
źródło
2
Teraz zastanawiam się, w ilu innych językach dwuwymiarowych to działa. Większość z nich w końcu opiera się na stosach.
1
Prawie działa w Cubix , ale wymaga wprowadzenia wiodącego .(lub dowolnego innego niż biały znak), aby przesunąć 0linię wykonania.
ETHproductions
1
Działa w Ouroboros , ale nie w ten sam sposób: interpreter próbuje czytać 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 program a(przesuwa 10 w nieskończoność).
DLosc
12

Java 101 bajtów

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

Ł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

masterX244
źródło
cóż, czuję się trochę głupio, że nie idę teraz z oczywistością, haha. Zaryzykuję stwierdzenie, że jest to bardziej eleganckie niż moje
Poke
1
tak, twój kod zapamiętał mnie do tego z finalize () @poke
masterX244
Myślę, że można by to skrócić, zastępując główny inicjatorem statycznym
tbodt
działa tylko do java6 i mam tylko wyższe wersje
masterX244
2
haha używa pojemnika na śmieci, aby spowodować wyciek! świetny pomysł :)
Mark K Cowan
12

Perl, 12 bajtów

{$"x=9;redo}

W perlu xoperator z ciągiem po lewej stronie i liczbą po prawej tworzy ciąg powtarzający się. Tak "abc" x 3ocenia 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.

redoOperator 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 :).

BenGoldberg
źródło
Pobiłeś mnie do tego! A twój jest trzy bajty krótszy.
Gabriel Benamy,
1
Wystarczyło przeszukać tę stronę w poszukiwaniu najmniejszej pętli :). Ponadto, początkowo miałem $_.=7w swojej pętli, ale zdałem sobie sprawę, że jeśli mógłbym x=go użyć , zabrakłoby pamięci znacznie szybciej, a następnie pobiegłem, perldoc perlvaraby wybrać coś odpowiedniego.
BenGoldberg,
{$^O++;redo}jest o jeden bajt krótszy, gdy ^Ojest o jeden chr(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.
Oleg V. Volkov
11

sed, 5 bajtów

Grał w golfa

H;G;D

Użycie (wystarczy dowolne wejście)

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

Wyjaśniono

#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

Zrzut ekranu

wprowadź opis zdjęcia tutaj

Wypróbuj online!

zepelin
źródło
2
Ściśle mówiąc, jest to GNU sed (średnik nie jest standardowym sedem), ale nowa linia i tak działałaby równie dobrze jak średnik.
R ..
10

Haskell, 23 19 bajtów

main=print$sum[0..]

Wydrukuj sumę nieskończonej listy

Angs
źródło
Jest to dobry sposób na wymuszenie oceny, a także jest bardzo kompaktowy. +1
Esolanging Fruit
kompilator mógłby bardzo dobrze uruchomić to w pamięci O (1). W GHC sumdefiniuje się jako foldl (+) 0i co zatrzymać analizę rygorystyczności, aby rozpocząć, aby zapobiec wydmuchiwaniu? Czy uruchomiłeś go skompilowany z optymalizacjami?
Czy Ness
@WillNess Jaka może być odpowiedź? sumnie będzie wiedział z góry, że lista jest nieskończona i printsumę należy najpierw ocenić. I tak, skompilowałem to z optymalizacjami
Angs
nie byłoby odpowiedzi; ale obliczenia byłyby wykonywane w przestrzeni O (1). Ups, Integeruderz , że z powodu domyślnej liczby są nieograniczone, a pamięć zajęta przez bieżący wynik bignum rzeczywiście by się powiększyła.
Czy Ness
1
aby wyjaśnić, miałem na myśli to, że obliczenia sum xs = foldl (+) 0 xsmogą przebiegać w trybie ciągłego stosu, tak jak w przypadku każdej pętli imperatywnej . foldl' (+) 0 xsna pewno będzie. Tak więc jedyną rzeczą przydzielającą pamięć na pewno jest tymczasowy wynik bignum.
Czy Ness
9

C ++ (przy użyciu kompilatora g ++), 27 23 15 bajtów

Dzię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.

main(){main();}

Alternatywne rozwiązanie

To rozwiązanie przecieka pamięć.

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

Wyjście Valgrind

Jest to wyjście Valgrind po zakończeniu programu na kilka sekund przed uruchomieniem. Widać, że z pewnością przecieka pamięć.

==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
Kreator pszenicy
źródło
3
Tytuł wprowadza w błąd; pytanie brzmi: „napisać program, który działa wiecznie i stale przydziela pamięć”.
NobodyNada
Och, nie zdawałem sobie sprawy, że już przesłałeś odpowiedź, kiedy wysłałem swoją.
Neop
1
@Neop Cóż, nie wiedziałem, że możesz zwolnić, int dopóki nie zobaczyłem twoich podziękowań!
Wheat Wizard
2
Nie C++, tylko jego dialekt g ++: C ++ zabrania wywoływania main; C ++ wymaga int main...deklaracji. Ale rozwiązanie jest nadal fajne :-)
Martin Ba
1
Rzeczywiście, C ++ zabrania dzwonienia main.
R ..
9

JAWA, 81 79 78 bajtów

JAVA (HotSpot) 71 70 bajtów

Krótszy niż inne odpowiedzi Java w momencie, gdy publikowałem (81, później 79 bajtów):

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

Jak sugeruje @Olivier Grégoire, można zapisać kolejny bajt:

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

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+=xrównież działa:

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

Które mogą również skorzystać z porady @Olivier Grégoire:

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

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 xnigdy nie ucieka od funkcji lokalnej. Użycie intern()pozwala uniknąć tego problemu, ponieważ internowane łańcuchy ostatecznie są przechowywane w polu statycznym. Jednak HotSpot generuje OutOfMemoryErrordla tego kodu, więc myślę, że jest w porządku.

Aktualizacja: @Olivier Gregoire wskazał również, że x+=xkod może się uruchamiać, StringIndexOutOfBoundsExceptiona nie OOMkiedy jest dużo pamięci. Wynika to z faktu, że Java używa typu 32-bitowego intdo indeksowania tablic (a ciągi to tylko tablice char). Nie wpływa to na x+=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.

DepressedDaniel
źródło
Witamy w PPCG! Nie znam zbyt dobrze Javy; co by się stało, gdybyś to zrobił x+=x;?
ETHproductions
możesz ogolić średnik, odkładając x+=x.intern()ostatni średnik pętli for
masterX244
Niezła odpowiedź. Wiedziałem, że musi być coś z sznurkiem, internale 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.
Poke
Jeśli twoja odpowiedź zależy od konkretnej implementacji Java i niekoniecznie będzie przenośna dla wszystkich implementacji Java, możesz umieścić informacje w tytule (np # 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.
1
humm ... x+=x;nie wyczerpuje całej pamięci. Z 64 GB dostaję StringIndexOutOfBoundsExceptionOOM, a nie OOM. Z .intern()nadal dostaję OOM.
Olivier Grégoire,
8

Perl 6 , 13 bajtów

@= eager 0..*

Wyjaśnienie:

@ = zapisz wynik w nienazwanej tablicy

eager spraw, aby poniższa lista była chętna

0 .. * nieskończony zakres, zaczynając od zera

Brad Gilbert b2gills
źródło
8

///, 7 bajtów

/a/aa/a

Stale wymieniać az aaad nauseum.

Steenbergh
źródło
12
*aad naauseum
timothymh,
1
* ad nauseam=>aad naauseaam
Aaron,
Co //a/? To wydaje się na zawsze zastępować `` (nic) a, ale nie jestem pewien, czy jest to dokładnie określone.
Cedric Reichenbach,
6

Python 3, 16 bajtów

i=9
while 1:i*=i

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).

sztuczny zero
źródło
Tytuł sugeruje, że pamięć powinna zostać wyciekła. Ale to tak naprawdę nie przecieka pamięci. Autor powinien chyba to wyjaśnić.
Wheat Wizard
6

Rdza, 46 bajtów

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

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.

Harald Korneliussen
źródło
6

Zestaw sześciokątny TI-83, 7 bajtów

PROGRAM:M
:AsmPrgm
:EF6A4E
:C3959D
:C9

Tworzy appvars w nieskończoność, dopóki system ERR:MEMORYoperacyjny nie wyrzuci znaku an . Uruchom z Asm(prgmM). Liczę każdą parę cyfr szesnastkowych jako jeden bajt.

Złupić
źródło
6

Python, 8 bajtów

2**9**99

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**10011 bajtów), ale naiwnie, podstawa logarytmiczna 2 liczby to

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

tj. 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).

asmeurer
źródło
5

Galaretka , 3 2 bajty

-1 bajt dzięki Dennisowi ( Wokł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 ...

Jonathan Allan
źródło
Jeśli dobrze rozumiem zasady, ‘ßpowinno być dużo.
Dennis
Czy to naprawdę „stale przydziela pamięć” (myśląc o Pythonie utrzymującym stały przydział dla małych int)?
Jonathan Allan,
1
Słusznie. nadal powinien pasować do rachunku.
Dennis,
5

Java 7, 106 bajtów

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

Mniej golfa

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

finalizeWywoł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. W mainpę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

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

Mniej golfa

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

To jest zabawne bardziej niż cokolwiek innego. Ta odpowiedź korzysta z Unsafebiblioteki Sun, która jest nieudokumentowanym wewnętrznym interfejsem API. Może być konieczna zmiana ustawień kompilatora, aby umożliwić ograniczone interfejsy API. Unsafe.allocateMemoryalokuje 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łania Unsafe.freeMemorylub do wyczerpania się pamięci JVM.

Szturchać
źródło
1
Zastanawiałem się, czy zobaczę tutaj Javę.
Magic Octopus Urn
Czy pierwszy nie działa tylko wtedy, gdy moduł wyrzucania elementów bezużytecznych działa w osobnym wątku?
tbodt
@tbodt tak, ale nie sądzę, że tak nigdy nie jest. Odśmiecanie odbywa się w demonicznym wątku zwanym odśmiecaczem
Poke
@Poke jest to gwarantowane? jeśli nie, odpowiedź jest nadal w porządku, ale należy wyjaśnić, że działa ona tylko wtedy, gdy
moduł
@tbodt Myślę, że tak, ale nie jestem pewien, szczerze.
Poke
5

Haskell, 24 bajty

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

Głównym problemem w Haskell jest pokonanie lenistwa. mainmusi mieć jakiś IOtyp, więc zwykłe dzwonienie main=f 9nie zadziała. Użycie main=pure(f 9)podnosi typ f 9do IOtypu. Jednak używanie konstrukcji typu main=pure 9nic nie robi, 9jest zwracane lub wyświetlane nigdzie, ale po prostu odrzucane, więc nie trzeba oceniać argumentu pure, a zatem main=pure(f 9)nie powoduje przydzielania pamięci, ponieważ fnie jest wywoływana. Aby wymusić ocenę, $!operator istnieje. Po prostu stosuje funkcję do argumentu, ale najpierw ocenia argument. Tak więc używanie main=pure$!f 9ewaluuje, fa zatem stale przydziela więcej pamięci.

Laikoni
źródło
Po skompilowaniu środowisko wykonawcze wykrywa pętlę i przerywa wykonywanie
Angs
@Angs Skompilowałem z ghc w systemie Windows i nadal szczęśliwie przydziela pamięć ... Zatrzymałem go na 3 GB.
Laikoni,
Używanie f x=f xteż działa, prawda? (−2 bajty)
wchargin
@wchargin Nie sądzę, f x=f xtworzy nieskończoną pętlę, ale bez przydzielania nowej pamięci.
Laikoni,
Fajnie, powodując wysadzenie pamięci w obliczeniach bignum! f!x=x*f(x*x)powinien być odporny na optymalizacje.
Czy Ness
5

dc, 7 bajtów

[ddx]dx

[ddx]wypycha na stos ciąg zawierający „ddx”. dxduplikuje 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.

faubi
źródło
Chwila, więc wykładniczo przydzieliłoby pamięć, gdyby mogła działać równolegle?
HyperNeutrino,
5

Haskell (przy użyciu ghc 8.0.1), 11 bajtów

m@main=m>>m

Rekurencja bez ogona. mainwywołuje siebie, a potem siebie ponownie.

nimi
źródło
Czy to alokuje na stercie lub stosie? (Mogę w to uwierzyć; może to zależeć od kompilatora Haskell w zastosowaniach.)
1
@ ais523: to zależy. Haskell nie ma stosu wywołań . System czasu pracy RTS ma obszar pamięci do dopasowywania wzorców, który jest również nazywany „stosem”. Ten stos jest przydzielany na stercie. Szczerze mówiąc, nie wiem, co się tutaj dzieje, ponieważ program nie działa z 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.
nimi
1
@ ais523: wydaje się, że w pamięci pojawia się błąd w komunikacie o błędzie ghc, więc trudno powiedzieć, co dokładnie się stanie.
nimi
Skompilowane w GHC 7.10.3 na Ubuntu, wydaje się, że zajmuje to stałą ilość pamięci, nawet gdy optymalizacje są wyłączone
Angs
@Angs: hmm, używam ghc 8.0.1 na MacOS. Zmienię to w.
nimi
5

C (linux), 23 bajty

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

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 w VIRTpolu danych topwyjś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

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

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ą elementy malloc()wewnętrzne.

Cyfrowa trauma
źródło
Dzięki malloc nie piszesz bezpośrednio w pamięci, ponieważ malloc niczego nie inicjuje. Pamięć jest przydzielana tylko dlatego, że malloc potrzebuje trochę pamięci wewnętrznej do zarządzania pamięcią. Więc odpowiedź nie jest tak naprawdę standardowa, ale chyba i tak działa wszędzie.
Antzi
@Antzi Tak. Myślę jednak, że to nadal działa, ponieważ chociaż pamięć użytkownika może nie zostać faktycznie przydzielona przed jej zapisaniem, każdy malloc()blok ed musi nadal mieć swoje prawdziwe przydzielone miejsce. Działa to na macOS i Ubuntu.
Cyfrowy uraz
Warunek w pytaniu, na którym każda strona jest napisana, jest raczej pozbawiony znaczenia; nawet jeśli chcesz założyć, że system operacyjny nie wykonuje prawidłowej ewidencji zatwierdzeń, niezależnie od szczegółów implementacji, koniecznie jest niezerowa ilość księgowości na alokację. Niezależnie od tego, czy przylega do przydziału (powodując dotknięcie stron), czy nie, ostatecznie zużyje dowolną ilość pamięci do prowadzenia ksiąg rachunkowych z (koniecznie) niezerowymi danymi.
R ..
Możesz go zmniejszyć o jeden bajt main(){main(malloc(9));}, ale aby nie przepełniać stosu, wymaga optymalizacji wywołania ogona, a gcc nie chce tego robić w dniu main...
R ..
Jeśli zamienisz malloc (9) na calloc (9,9), wówczas zostanie przydzielona wystarczająca ilość pamięci dla 9 wystąpień bloku 9-bajtowego (czyli między 81 a 144 bajtów, w zależności od wyrównania. Jednak, co ważniejsze, calloc ( ) wypełni zero bloku pamięci, zmuszając podstawowy system operacyjny do przydzielenia pamięci.
CSM
5

Perl, 4 bajty

do$0

Wykonuje się w bieżącym tłumaczu. Po zakończeniu wykonanie powraca do skryptu wywołującego, który wymaga stosu wywołań.

primo
źródło
Ładne i krótkie, choć nie marnuje pamięci tak szybko jak moja.
BenGoldberg,
4

Rakieta, 13 bajtów

(let l()(l)1)

Nie jestem całkowicie pewien, czy moja odpowiedź mieści się w tym pytaniu. Daj mi znać, czy powinienem usunąć tę odpowiedź.

Winny
źródło
Czy możesz wyjaśnić, jak to działa?
tbodt
1
och, więc definiuje się to ljako funkcję, która wykonuje rekurencję bez wywołania ogona. powiedziałbym, że to się liczy.
tbodt
@tbodt tak, masz rację co do pieniędzy
Winny
4

JavaScript 22 21 17 16 15 bajtów

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

Zaoszczę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)

f=a=>f([a]);f()
Lmis
źródło
1
Czy na drugim przykładzie z ES6 nie możesz tego zrobić f=_=>f();f()? 12 bajtów
ugryziony
@ ugryziony Nie jestem pewien. Jeśli liczy się wysadzenie stosu wywołań, to ten, który nie ma odpowiednich wezwań ogona, byłby właściwą drogą. Jeśli chodzi o TCO, nie sądzę, żeby wyciekała pamięć, prawda?
Lmis,
oba obalają dla mnie stos wywołań . Nie znam się na ogonach, więc nie mogę tego komentować.
ugryziony
1
Ach, rozumiem, nie byłem pewien, jak twoje wycieka pamięć
ugryziony
1
Możesz usunąć a=0. Pierwsza iteracja spowodowałabya=[undefined]
Florent
4

Rubinowy, 11 bajtów

loop{$*<<9}

Naciska 9na $*, która jest tablicą początkowo przechowującą argumenty wiersza poleceń dla procesu Ruby.

daniero
źródło
4

05AB1E , 2 bajty

[A

Wypróbuj online! Będzie po prostu naciskać abcdefghijklmnopqrstuvwyxzna stos na wieczność.

Wszystkie możliwe rozwiązania 2-bajtowe:

[  # 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 Magicznej Ośmiornicy
źródło
Bardzo dokładny! Miły.
timothymh,
3

Python, 35 bajtów

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

a nigdy nie jest wypuszczany i tylko staje się większy, dopóki nie trafisz MemoryError

Możesz zobaczyć wykonanie w Python Tutor .

Noelkd
źródło
1
Można to zrobić a+=a,?
Cyoce,
Nie potrzebuję żadnej funkcji, oto moja gra w golfa
FlipTack
@ Flp.Tkc pytanie zostało zmienione po napisaniu tej odpowiedzi Zrobiłbym to, co zrobiłeś (+ - kilka znaków), gdyby był w obecnym formacie.
Noelkd,
3

TI-BASIC, 8

:Lbl A
:While 1
:Goto A

(wszystkie 1-bajtowe tokeny i dwa znaki nowej linii)

Powoduje to ciągłe wycieki pamięci, ponieważ ustrukturyzowany przepływ sterowania, taki jak Whileprzewidywane zamknięcie przez Endi, wypycha coś na stos (nie na stos operacyjny, oddzielny stos w pamięci stosu), aby to śledzić. Ale tutaj używamy Gotodo opuszczenia pętli (więc nie Endjest wykonywane żadne polecenie usunięcia rzeczy ze stosu), to Whilejest ponownie widoczne, rzecz jest ponownie wypychana itp. Więc po prostu ją popycha, dopóki nie pojawi sięERR:MEMORY

Harold
źródło