Найкоротша програма, яка постійно виділяє пам'ять


49

Напишіть програму, яка працює назавжди і виділяє все більше пам’яті на купі, чим довше вона працює, принаймні, поки ви не досягнете межі операційної системи щодо обсягу пам’яті, яку можна виділити.

Багато ядер фактично не резервують виділену вами пам’ять, поки ви її не використовуєте для чогось, тому, якщо ваша програма знаходиться на мові C або на якійсь іншій мові низького рівня, вам доведеться обов’язково щось написати на кожну сторінку. Якщо ви використовуєте інтерпретовану мову, вам, мабуть, не доведеться турбуватися з цього приводу.

Найкоротший код виграє.


13
Чи переповнення стека є дійсним рішенням? Чи потрібно пам'ять просочуватися або просто виділяти?
Пшеничний майстер

1
@WheatWizard Пам'ять не повинна просочуватися, але вона повинна розподілятися швидше, ніж вона розміщена.
tbodt

2
Коли я хочу, щоб моя програма споживала нескінченну пам'ять, я не можу її отримати. (reduce conj [] (range))(Clojure) набирає до 737mb, потім просто перестає рости. Подумайте, як це постійно не піднімається. Він "думає", що я хочу надрукувати весь список наприкінці, тому не слід нічого викидати. Дуже засмучує.
Carcigenicate

14
Примітка до самостійного використання: Збережіть код перед тестуванням. Введення витоків пам’яті може призвести до аварії IDE ...
steenbergh

1
Я думаю, вам слід додати ще один виклик для гольфу, подібний, але окремий до цього, вимагаючи, щоб програма споживала пам'ять швидше, ніж лінійна функція часу. Для поточного виклику, циклічно назавжди та виділення єдиного байта має бути добре. Для вашого нового завдання це буде недостатньо, але циклічно назавжди та подвоєння обсягу пам'яті, що використовується щоразу, було б нормально.
БенГольдберг

Відповіді:


46

Funge-98 ( cfunge), 1 байт

9

Я б опублікував це раніше, але вирішив протестувати, і для того, щоб повернути комп’ютер у стан, що потрібний, знадобився певний час. cfungeзберігає стек Funge на купі операційної системи (що легко перевірити, запустивши програму з невеликим обмеженням пам’яті, що я повинен був зробити раніше!), так що нескінченно зростаючий стек (як у цій програмі, яка просто 9повторно натискає ; Програми Funge, що обгортають від кінця рядка до початку за замовчуванням), назавжди виділять пам'ять. Ця програма, ймовірно, працює і в деяких реалізаціях Befunge-93.

Більш цікавим:

"NULL #(4

Це була моя перша ідея, і це нескінченне виділення, яке не покладається на стек Funge (хоча воно також підірває стек Funge). Для початку "команда висуває копію решти програми до стеку (це рядок, а програма завертається кругом, тому закрита цитата також виконує роль відкритої цитати). Тоді Nвідображення (воно не має значення за замовчуванням), викликаючи запуск програми назад. У "пробіги знову, і штовхає програму в стек - навпаки цей час, з Nна вершині стека - то програма обтікає, завантажуючи бібліотеку з ім'ям 4-літерного ( 4(, а NULLбібліотека є частиною cfungeстандартна бібліотека). NULLвизначає всі великі літери, які потрібно відображати, тому Lвідображення,#пропускає завантаження бібліотеки на зворотному шляху, 4штовхає мотлох, про який ми не піклуємось, і вся програма повторюється з самого початку. Зважаючи на те, що завантаження бібліотеки кілька разів має ефект і вимагає, щоб список команд бібліотеки зберігався один раз для кожної копії бібліотеки (це мається на увазі в семантиці Funge-98), вона просочується пам’яттю через не стекове зберігання (що є альтернативний метод визначення "купи" щодо мови, а не ОС).


2
Я просто прийму це ...
tbodt

Чи потрібно, щоб число було 9? Це також спрацювало, якби було 5?
tbodt

Все, що підштовхується до стека, працює (крім можливого 0; можливо, впровадження Funge або ОС могли знайти спосіб оптимізувати це, враховуючи, що об'єм пам'яті вже заповнений нулями). Я просто вибрав 9довільно.

22
Неприйнятний, тому що я хочу, щоб моя репутація все ще була 666.
tbodt

7
@tbodt Не справжня причина не приймати. Якщо ви хочете, я постану -1 ваше запитання. Тоді, коли ви приймете, у вас буде ще 703 (зауважте, зараз у вас 703, а не 666).
NoOneIsHere

30

Brainfuck, 5 байт

+[>+]

Для цього потрібен перекладач, який не обмежує довжину стрічки.


2
Я впевнений, що це + [> +], інакше він просто зупиниться на першій ітерації. ;)
Паріс Дуаді

Ви маєте рацію, вибачте за друкарські помилки.
vsz

40
Один з рідкісних випадків, коли рішення про епізод є конкурентоспроможним ...
FlipTack

@ Flp.Tkc Але він все одно програє. Можливо, він колись переможе ...
NoOneIsHere

6
@SeeOneRhino: Він вже один раз виграв, перемігши всі мови для гри в гольф> codegolf.stackexchange.com/questions/8915/…
vsz

22

Bash + coreutils, 5

або

Рубі, 5

`yes`

yesдає нескінченний вихід. Якщо вставити yesзадні посилання, вказує оболонка, щоб захопити весь вихід, а потім виконати цей вихід у вигляді команди. Bash буде продовжувати виділяти пам'ять для цієї нескінченної струни, поки купа не закінчиться. Звичайно, отриманий результат у результаті виявиться недійсною командою, але нам не вистачить пам'яті, перш ніж це станеться.

Завдяки @GB за вказівку, це і поліглот у рубіні.


7
Я збирався написати те саме і назвати це програмою Ruby.
ГБ

1
і перл, я думаю.
abligh

18

Пітон, 16 байт

Тримає вкладення, aпоки не буде досягнуто помилки:

a=0
while 1:a=a,

Перші кілька ітерацій (як кортежі) виглядають так:

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

і так далі, і так далі.


18

> <> (Риба), 1 байт

0

Спробуйте тут!

0 насправді може бути заміщене будь-яке шістнадцяткове число 1-f.

Пояснення

0в> <> просто робить 1x1 кодове поле для риби, щоб плавати. Це постійно додає 0на стек, плаває вправо, що петляється назад 0, додаючи його до стеку знову. Це триватиме назавжди.


2
Тепер мені цікаво, у яких інших двовимірних мовах це працює. Зрештою, більшість з них є на основі стека.

1
Практично працює в Cubix , але .для переміщення 0в рядок виконання потрібен головний (або будь-який непробільний знак) .
ETHproductions

1
Працює в Ouroboros , але не тим самим чином: інтерпретатор намагається читати 0000000...як єдине ціле буквальне, а рядок, який він створює, - це те, що вимагає більше пам'яті. Програма, яка працює так, як це було б a(натискає 10 нескінченно).
DLosc

12

Java 101 байт

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

Ловля основної програми в нескінченному циклі після створення та викидання об'єкта. Збір сміття виконує завдання протікання, створюючи 2 об’єкти для кожного видаленого


добре, я відчуваю себе трохи нерозумно за те, що не йду з очевидним зараз, ха-ха. Я б ризикну сказати, що це більш елегантно, ніж у мене
Poke

1
так, ваш код згадав мене про цей факт з finalize () @poke
masterX244

Я думаю, ви могли б скоротити її, замінивши main на статичний ініціалізатор
tbodt

працює лише до java6, і я отримав лише більш високі версії
masterX244

2
ха-ха за допомогою сміттєзбірника, щоб викликати протікання! чудова ідея :)
Mark K Cowan

12

Perl, 12 байт

{$"x=9;redo}

У perl xоператор із рядком зліва та числом праворуч створює повторний рядок. Так "abc" x 3оцінює до "abcabcabc".

x=Оператор мутує лівий аргумент, замінюючи вміст змінної на її зліва, в результаті повторення його зміст , як багато разів , як його права рука вказує.

Perl має низку ряду дивно названих вбудованих змінних, одна з яких є $", початкове значення якого є єдиним пробілом.

redoОператор переходить до початку огороджувальних {}.

Перший раз, коли x=оператор робиться, він змінює значення " $"з " "" на " "9 пробілів.

Другий раз, коли x=оператор виконаний, він змінює значення $"на " ", яке становить 81 пробіл.

Втретє $"стає 729-байтним довгим рядком пробілів.

Я думаю, ви можете бачити, куди це йде :).


Ти побив мене до цього! А ваш на три байти коротший.
Габріель Бенамі

1
Це було лише питання пошуку цього веб-сайту для найменшого циклу :). Крім того, я спочатку був $_.=7у своєму циклі, але зрозумів, що коли б я міг x=його використовувати, втрачав би пам'ять набагато швидше, а потім побіг perldoc perlvarвибрати щось підходяще.
БенГольдберг

{$^O++;redo}є на один байт коротше, коли ^Oце один chr(15)байт. Хоча це буде витрачати пам'ять набагато повільніше - потрібно 1000000000 ітерацій, щоб витратити один байт. Працює в будь-якій ОС, назва якої починається з латинської літери.
Олег Васильович Волков

11

sed, 5 байт

Гольф

H;G;D

Використання (будь-який вхід буде робити)

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

Пояснив

#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

Знімок екрана

enter image description here

Спробуйте в Інтернеті!


2
Власне кажучи, це GNU sed (крапка з комою не є стандартною sed), але нова лінія буде працювати так само добре, як і крапка з комою.
Р ..

10

Haskell, 23 19 байт

main=print$sum[0..]

Роздрукуйте суму нескінченного списку


Це хороший спосіб запровадити оцінку, і він дуже компактний. +1
Esolanging Fruit

компілятор міг би дуже добре запустити це в пам'яті O (1). У GHC sumвизначається як foldl (+) 0, і що потрібно зупинити аналіз суворості, щоб не допустити вибуху грона? Ви запускали його, складений з оптимізаціями?
Чи буде Несс

@WillNess Що може відповісти? sumне буде знати заздалегідь, що список нескінченний, і до printсуми його слід оцінити спочатку. І так, я склав це з оптимізаціями
Angs

відповіді не було б; але обчислення буде здійснюватися в просторі O (1). На жаль, зауважте, що через дефолт Integerцифри не є необмеженими, а пам'ять, отримана поточним результатом бінтуму , справді зростатиме.
Чи буде Несс

1
просто для уточнення, що я мав на увазі, що обчислення sum xs = foldl (+) 0 xsможе працювати в постійному стеці, як це робив би будь-який імперативний цикл . foldl' (+) 0 xsбезумовно, буде. Тож єдине, що виділяє пам'ять на певне, - це проміжний результат бінтуму.
Чи буде Несс

9

C ++ (використовуючи компілятор g ++), 27 23 15 байт

Дякую Neop за те, що допомогла мені видалити 4 байти

Це рішення насправді не протікає жодної пам'яті, оскільки воно виділяє все на стек і, таким чином, викликає переповнення стека. Він просто нескінченно рекурсивний. Кожна рекурсія призводить до виділення деякої пам’яті, поки стек не переповнений.

main(){main();}

Альтернативне рішення

Це рішення фактично просочує пам'ять.

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

Valgrind вихід

Це вихід Valgrind після закінчення програми на кілька секунд часу виконання. Ви можете бачити, що це, безумовно, просочується пам'ять.

==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
Назва вводить в оману; в запитанні сказано: "написати програму, яка працює вічно і постійно виділяє пам'ять".
НіхтоНада

О, я не розумів, що ви вже подали відповідь, коли я надіслав свою.
Неоп

1
@Neop Ну, я не знав, що ти можеш опустити, int поки я не побачив твоє так дякую!
Пшеничний майстер

2
Ні C++, лише діалект g ++ його: C ++ забороняє називати main; C ++ вимагає int main...декларації. Але рішення все ще акуратне :-)
Мартін Ба

1
Справді, C ++ забороняє дзвінки main.
Р ..

9

JAVA, 81 79 78 байт

JAVA (HotSpot) 71 70 байт

Коротше, ніж інші відповіді Java на час публікації (81, пізніше 79 байт):

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

Як запропонував @Olivier Grégoire, подальший байт можна зберегти:

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

Розміщення x+=x.intern()як збільшення для циклу не допоможе нічого, тому що крапка з комою все ще потрібна для завершення оператора for.

Як запропонував @ETHproductions, просто використання x+=xтворів також:

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

Що також може отримати користь від поради @Olivier Grégoire:

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

Моя єдина побоювання з цього приводу полягає в тому, що не гарантується розподіл даних по купі , оскільки ефективний JVM може легко зрозуміти, що xніколи не уникає локальної функції. Використання intern()дозволяє уникнути цього занепокоєння, оскільки інтерновані рядки в кінцевому підсумку зберігаються в статичному полі. Однак HotSpot дійсно генеруєOutOfMemoryError для цього коду, так що я думаю, що це добре.

Оновлення: @Olivier Gregoire також зазначив, що x+=xкод може працювати, StringIndexOutOfBoundsExceptionа не OOMколи багато пам'яті. Це тому, що Java використовує 32-розрядний intтип для індексації масивів (а Strings - це просто масиви char). Це не впливає на x+=x.intern()рішення, оскільки пам'ять, необхідна для останнього, є квадратичною по довжині рядка, і, таким чином, повинна масштабуватися до порядку 2 ^ 62 виділених байтів.


Ласкаво просимо до PPCG! Я не дуже добре знаю Java; що буде, якби ти щойно зробив x+=x;?
ETHproductions

ви можете поголити крапку з комою, поставивши x+=x.intern()позаду останню крапку з комою для циклу for
masterX244

Гарна відповідь. Я знав, що повинно бути щось із internструнною мовою, але я був дуже задоволений Небезпечним і довідався, що перестав шукати, ха-ха. Спочатку це питання вказувало на "витік пам'яті", тому я не просто відповів на стислий рядок.
Тикайте

Якщо ваша відповідь залежить від конкретної реалізації Java, і вона не обов'язково повинна бути переносимою для всіх реалізацій Java, ви можете розмістити інформацію в заголовку (наприклад # Java (HotSpot), 71 bytes). Таким чином, вам не потрібно турбуватися про рішення, яке потенційно може обдурити; Програми, характерні для впровадження, є поширеними не лише в гольфі, але і в широкому світі програмування, і якщо ви знаєте, що ви робите, іноді можуть бути більш підходящими, ніж портативна програма для, скажімо, одно- від сценарію.

1
гул ... x+=x;не вичерпує всю пам'ять. Маючи 64 ГБ, я отримую StringIndexOutOfBoundsException, а не МОМ. З .intern()я все ще отримую OOM.
Олів'є Грегоар

8

Perl 6 , 13 байт

@= eager 0..*

Пояснення:

@ = збережіть результат у безіменному масиві

eager зробити такий список нетерплячим

0 .. * нескінченний діапазон, починаючи з нуля



6

Python 3, 16 байт

i=9
while 1:i*=i

Це пов'язано з тим, що в Python 3 немає обмеження на цілий розмір; натомість цілі числа можуть займати стільки пам’яті, скільки система може обробити (якщо щось про моє розуміння цього невірно, виправте мене).


З назви випливає, що пам'ять має просочитися. Але це насправді не просочує пам'ять. Автору, мабуть, слід уточнити.
Пшеничний майстер

6

Іржа, 46 байт

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

Помічаєте щось цікаве про цю програму Rust, протікаючи виділення купи, поки не залишилося пам'яті?

Правильно, жодного небезпечного блоку. Іржа гарантує безпеку пам’яті у безпечному коді (відсутність читання неініціалізованих даних, читання після безкоштовного, подвійного вільного тощо), але витоки пам’яті вважаються абсолютно безпечними. Існує навіть явна функція, щоб змусити компілятор забути про очищення RAII із змінних областей, які я тут використовую.


6

TI-83 Шестигранна збірка, 7 байт

PROGRAM:M
:AsmPrgm
:EF6A4E
:C3959D
:C9

Створює appvars нескінченно, доки ERR:MEMORYОС не кинеться . Бігайте з Asm(prgmM). Я рахую кожну пару шістнадцяткових цифр як один байт.


6

Пітон, 8 байт

2**9**99

О.П. дозволило технічність програми , яка технічно не запустити «назавжди», але виділяє більше пам'яті , ніж будь-який комп'ютер міг впоратися. Це не зовсім googolplex (це було б 10**10**10011 байтів), але наївно, журнальна база 2 числа є

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

тобто 10 ^ 94 біт для його представлення. Вольфрам Альфа зазначає, що на 10 ^ 76 більше, ніж глибока павутина (майте на увазі, що у Всесвіті близько 10 ^ 80 атомів ).

Чому ви запитуєте 2 замість 9? Це не має великої різниці (використання 9 лише збільшить кількість бітів на коефіцієнт log2(9) = 3.2, який навіть не змінює показник). Але з іншого боку, програма працює набагато швидше з 2, оскільки розрахунок простіший. Це означає, що вона заповнює пам'ять негайно, на відміну від версії 9, яка займає трохи більше часу через необхідні розрахунки. Не потрібно, але приємно, якщо ви хочете "перевірити" це (що я і зробив).


5

Желе , 3 2 байти

-1 байт завдяки Деннісу ( Wобгортання)

Посилання (тобто функція чи метод), яка також працює як повноцінна програма, що рекурсивно перетворює свої дані у список.

Вхід починається з нуля, тому перший прохід створює список, [0]
другий пропуск потім робить це [[0]]
третій прохід, потім робить це [[[0]]]
і так далі ...


Попередній 3 байт, який протікає набагато швидше:

;Ẇß

рекурсивно з'єднує всі непусті суміжні підсписи його введення на свій вхід.
[0]-> [0,[0]]-> [0,[0],[0],[[0]],[0,[0]]]і так далі ...


Якщо я правильно розумію правила, ‘ßмає бути багато.
Денніс

Це дійсно "постійно виділяє пам'ять" (думаючи про постійне розподілення Python для невеликих ints).
Джонатан Аллан

1
Досить справедливо. все ж повинен відповідати законопроекту.
Денніс

5

Java 7, 106 байт

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

Менше гольф

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

finalizeМетод викликається для об'єкта складальником сміття , коли збірка сміття визначає , що більше немає посилань на об'єкт. Я просто переосмислив цей метод, щоб назавжди зациклюватися, щоб сміттєзбірник ніколи фактично не звільняв пам'ять. У mainциклі я створюю нові об'єкти, які ніколи не будуть очищені, тому в підсумку це задіяє всю наявну пам'ять.

Java 7 (весела альтернатива), 216 байт

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

Менше гольф

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

Це веселіше більше, ніж усе інше. У цій відповіді використовується Unsafeбібліотека Sun, яка є незадокументованим внутрішнім API. Можливо, вам доведеться змінити налаштування компілятора, щоб дозволити обмежені API. Unsafe.allocateMemoryвиділяє вказану кількість байтів (без будь-якої перевірки меж), яка знаходиться не в купі і не знаходиться під управлінням збирання сміття Java, тому ця пам'ять буде триматися навколо, поки ви не зателефонуєте Unsafe.freeMemoryабо поки у jvm не закінчиться пам'ять.


1
Цікаво, чи побачу я тут Java.
Чарівна урва восьминога

Чи не працює перший лише, якщо сміттєзбірник працює окремою ниткою?
tbodt

@tbodt так, але я не вірю, що це колись не так. Збір сміття відбувається в демоновій нитці під назвою збирач сміття
Poke

@ Poke це гарантовано? якщо ні, відповідь все ще гарна, але ви повинні уточнити, що вона працює лише в тому випадку, якщо збирач сміття працює у власній нитці
tbodt

@tbodt Я так думаю, але я не впевнений, чесно.
Пік

5

Haskell, 24 байти

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

Основна проблема Хаскелла - перемогти лінь. mainпотрібно мати певний IOтип, тому просто дзвонити main=f 9не вийде. Використання main=pure(f 9)піднімає тип f 9на IOтип. Однак використання таких конструкцій main=pure 9нічого не робить, 9повертається або відображається нікуди, а просто відкидається, тому немає необхідності оцінювати аргумент pure, отже main=pure(f 9), не викликає виділення жодної пам'яті, як fне викликається. Для примусового оцінювання $!оператор існує. Він просто застосовує функцію до аргументу, але спочатку оцінює аргумент. Тому використання main=pure$!f 9оцінок fі, отже, постійно виділяє більше пам’яті.


Під час компіляції час виконання виявляє цикл і порушує виконання
Angs

@Angs Я компілював з ghc на windows, і він продовжує радісно розподіляти пам'ять ... Я зупинив його на 3 Гб.
Лайконі

Використання f x=f xтворів теж, правда? (−2 байти)
wchargin

@wchargin Я не думаю, що f x=f xстворює нескінченний цикл, але не виділяючи нову пам'ять.
Лайконі

Мило, спричиняючи вибух пам'яті за допомогою розрахунків бінтуму! f!x=x*f(x*x)має зробити його оптимізаційними.
Чи буде Несс

5

постійного струму, 7 байт

[ddx]dx

[ddx]висуває в стек рядок, що містить "ddx". dxдублює його, потім виконує його як код (залишаючи одну копію в стеку). Коли він виконується, він робить два дублікати, а потім виконує один, залишаючи ще одну копію в стеці кожен раз.


Зачекайте, щоб це експоненціально розподіляло пам'ять, якби вона могла працювати паралельно?
HyperNeutrino

5

Haskell (використовуючи ghc 8.0.1), 11 байт

m@main=m>>m

Безхвильова рекурсія. mainназиває себе, а потім знову себе.


Це виділяє на купі чи на стеці? (Я можу повірити будь-якому; це може цілком залежати від компілятора Haskell у використанні.)

1
@ ais523: це залежить. У Haskell немає стека викликів . Система часу роботи RTS має область пам'яті для узгодження шаблонів, яку також називають "стек". Цей стек виділяється на купі. Чесно кажучи, я не знаю, що тут відбувається, тому що програма виходить з ладу з Stack space overflow: current size 33624 bytes.33k, здається, досить низькою на відміну від 6G загальної пам'яті, про яку звітує ОС.
німі

1
@ ais523: напевно, помилка в інформації про пам'ять повідомлення про помилку ghc, тому важко сказати, що саме відбувається.
німі

Скомпільовано на GHC 7.10.3 на Ubuntu, здається, це потребує постійного обсягу пам'яті, навіть коли оптимізація відключена
Angs

@Angs: Хм, я використовую ghc 8.0.1 на MacOS. Я відредагую це.
Німі

5

C (linux), 23 байти

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

sbrk() збільшує верхню частину сегмента даних на задану кількість байтів, тим самим ефективно збільшуючи обсяг пам'яті, виділеної програмі - принаймні, як повідомляється в VIRT полі topвиводу. Це працює лише в Linux - реалізація macOS, мабуть, емуляція, яка дозволяє виділяти лише до 4 МБ.


Отже, трохи більш загальна відповідь:

C, 25 байт

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

Я спостерігав за цим монітором активності macOS. Він пройшов аж до 48 Гб, а згодом процес отримав сигнал SIGKILL. FWIW моя MacBook Pro має 16 Гб. Більшість використовуваної пам'яті було зареєстровано як стиснуте.

Зауважте, що питання фактично вимагає писати кожен розподіл, що тут явно не відбувається. Однак важливо зазначити, що для кожного malloc(9)дзвінка виділяються не лише 9 запитуваних користувачем байтів. Для кожного виділеного блоку буде заголовок malloc, який також виділяється звідкись у купі, що обов'язково записується malloc()внутрішніми.


З malloc ви не пишете безпосередньо в пам'ять, оскільки malloc нічого не ініціалізує. Пам'ять виділяється лише тому, що malloc потребує деякого внутрішнього сховища для управління пам'яттю. Тож відповідь насправді не стандартна, але я думаю, що вона працює скрізь.
Анци

@Antzi Так. Однак я думаю, що це все ще працює, тому що, хоча пам’ятка користувача фактично не може бути розподілена до того, як вона буде записана, у кожного malloc()блоку ed все одно має бути власне виділене місце. Це працює на macOS та Ubuntu.
Цифрова травма

Умова у питанні кожної сторінки, на яку написано, є досить безглуздою; навіть якщо ви хочете припустити, що ОС не здійснює належного обліку фіксації зобов'язань, незалежно від відомостей про впровадження, обов'язково потрібна ненульова сума бухгалтерії, необхідна на розподіл. Незалежно від того, суміжний він із розподілом (спричиняючи торкання сторінок) чи ні, він з часом споживає довільну кількість пам'яті для ведення бухгалтерського обліку з (обов’язково) ненульовими даними.
Р ..

Ви можете отримати його на один байт меншим розміром main(){main(malloc(9));}, але для того, щоб не переповнювати стек, йому потрібна оптимізація хвостових викликів, і gcc, схоже, не хоче цього робити на main...
R ..

Якщо ви заміните malloc (9) на calloc (9,9), то буде достатньо пам'яті, виділеної на 9 примірників 9-байтового блоку (тобто між 81 і 144 байтами, залежно від вирівнювання. Однак, і що ще важливіше, calloc ( ) заповнить нуль блоку пам'яті, змусивши базову ОС виділити йому сховище.
CSM

5

Perl, 4 байти

do$0

Виконує сам, у поточному перекладачі. По завершенні виконання повертається до скрипта виклику, для якого потрібен стек викликів.


Приємний і короткий, хоча пам’ять не втрачає швидко, як моя.
BenGoldberg

4

Ракетка, 13 байт

(let l()(l)1)

Я не зовсім впевнений, якщо моя відповідь підпадає під це питання. Будь ласка, дайте мені знати, чи потрібно видаляти цю відповідь.


Чи можете ви пояснити, як це працює?
tbodt

1
о, значить, це визначається lяк функція, яка робить нереактивну рекурсію. я б сказав, що це враховує.
tbodt

@tbodt так, ти правий на гроші
Вінні

4

JavaScript 22 21 17 16 15 Байт

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

Збережено 4 байти, перегорнувши список в інший список, як у відповіді Желяна @Jonathan Allan's Jelly.

Збережено 1 байт завдяки @ETHProductions

Альтернативне рішення 15 байт (працює лише при правильних викликах хвоста)

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

1
На вашому другому прикладі з ES6, ви не могли просто зробити це f=_=>f();f()? 12 байт
покусав

@bitten Я не впевнений. Якщо рахувати, що підірватиме стек викликів, то цей шлях без належних хвостових дзвінків стане дорогою. З TCO, я не думаю, що пам'ять просочилася б, чи не так?
Лміс

обидва дують стек викликів для мене . Я не дуже знайомий з хвостовими дзвінками, тому не можу це коментувати.
покусав

1
ах я бачу, я не був впевнений, як у вас просочилася пам’ять
покусав

1
Можна було видалити a=0. Перша ітерація призведе доa=[undefined]
Флорент

4

Рубін, 11 байт

loop{$*<<9}

Тримає натискання 9на $*- це масив, який спочатку містить аргументи командного рядка до процесу Ruby.


4

05AB1E , 2 байти

[A

Спробуйте в Інтернеті! Просто буде продовжувати натискати abcdefghijklmnopqrstuvwyxzна стек на вічність.

Усі можливі 2-байтні рішення:

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

Дуже ретельно! Приємно.
Тимофім

3

Пітон, 35 байт

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

a ніколи не звільняється і просто збільшується, поки ви не натиснете на MemoryError

Ви можете переглянути виконання в Python Tutor .


1
Можна зробити a+=a,?
Кіос

Не потрібно ніякої функції, ось мій гольф її
FlipTack

@ Flp.Tkc питання було змінено після того, як я написав цю відповідь, я зробив би те, що ви зробили (+ - пара символів), якби це було у його нинішньому форматі.
Ноелькд

3

TI-BASIC, 8

:Lbl A
:While 1
:Goto A

(усі 1-байтні жетони та два нові рядки)

Це безперервно протікає пам'ять, оскільки структурований потік управління, такий як Whileочікуване, буде закритий Endі штовхає щось на стеку (не стек ОС, окремий стек у купі пам'яті), щоб відстежувати це. Але тут ми використовуємо Gotoдля того, щоб залишити цикл (тому жодне Endне виконується, щоб вийняти річ зі стека), Whileзнов видно, річ знову натискається і т. Д. Тому вона просто продовжує натискати на них, поки не отримаєтеERR:MEMORY

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.