Напишите программу, которая работает вечно и выделяет все больше и больше памяти в куче, чем дольше она работает, по крайней мере, пока вы не достигнете предела операционной системы по объему памяти, который может быть выделен.
Многие ядра на самом деле не зарезервируют память, которую вы выделяете, пока не используете ее для чего-то, поэтому, если ваша программа написана на C или каком-либо другом низкоуровневом языке, вам нужно будет обязательно что-то написать для каждой страницы. Если вы используете интерпретированный язык, вам, вероятно, не придется беспокоиться об этом.
Самый короткий код выигрывает.
(reduce conj [] (range))
(Clojure) получает до 737mb, а затем просто перестает расти. Я думаю, что это не постоянно идет вверх. Он «думает», что я хочу напечатать весь список в конце, поэтому он не должен ничего выбрасывать. Очень расстраивает.Ответы:
Funge-98 (
cfunge
), 1 байтЯ бы опубликовал это раньше, но решил протестировать его, и потребовалось некоторое время, чтобы вернуть мой компьютер в рабочее состояние.
cfunge
хранит стек Funge в куче операционной системы (которую легко проверить, запустив программу с небольшим ограничением памяти, что я и должен был сделать раньше!), таким образом, бесконечно растущий стек (как с этой программой, которая просто выдвигает9
несколько раз; Программы Funge, перенесенные с конца строки на начало по умолчанию, будут выделять память навсегда. Эта программа, вероятно, также работает в некоторых реализациях Befunge-93.Интереснее:
Это была моя первая идея, и она представляет собой бесконечное распределение, которое не зависит от стека Funge (хотя оно также разрушает стек Funge). Для начала,
"
команда помещает копию остальной части программы в стек (это строка, и программа оборачивается, поэтому закрывающая кавычка также служит открытой кавычкой). ЗатемN
отражается (по умолчанию это не имеет смысла), вызывая запуск программы в обратном направлении. В"
пробеги снова, и толкает программу в стек - наоборот это время, сN
на вершине стека - то программа обтекает, загружая библиотеку с именем 4-буквенного (4(
, аNULL
библиотека является частьюcfunge
стандартная библиотека).NULL
определяет все заглавные буквы , чтобы сделать отражать, так чтоL
отражает, то#
скачет библиотеки нагрузки на пути обратно,4
выталкивает барахло мы не заботимся о том, чтобы стек и всей программе повторяется с самого начала. Учитывая, что загрузка библиотеки несколько раз имеет эффект, и требует, чтобы список команд библиотеки хранился один раз для каждой копии библиотеки (это подразумевается семантикой Funge-98), это приводит к утечке памяти через не стековое хранилище (которое является альтернативный метод определения «кучи», относительно языка, а не ОС).источник
0
, возможно, что реализация Funge или ОС могли бы найти способ оптимизировать это, учитывая, что рассматриваемая память уже заполнена нулями). Я просто выбрал9
произвольно.Brainfuck, 5 байтов
Для этого требуется переводчик, который не имеет ограничений по длине ленты.
источник
Bash + coreutils, 5
или же
Руби, 5
yes
производит бесконечный выход. Заданиеyes
обратных галочек говорит оболочке перехватить весь вывод и затем выполнить этот вывод как команду. Bash продолжит выделять память для этой бесконечной строки, пока не закончится куча. Конечно, в результате вы получите недопустимую команду, но мы должны исчерпать память, прежде чем это произойдет.Спасибо @GB за указание, что это полиглот и в рубине.
источник
Python, 16 байт
Сохраняет вложение,
a
пока не будет достигнута ошибка:Первые несколько итераций (в виде кортежей) выглядят так:
и так далее и тому подобное.
источник
> <> (Рыба), 1 байт
Попробуй это здесь!
0
может на самом деле заменить любое шестнадцатеричное число 1-е.объяснение
0
in> <> просто создает кодовое поле 1x1, в котором рыба может плавать. Она постоянно добавляет0
в стек, плавает вправо, что делает возврат в обратном направлении0
, снова добавляя его в стек. Это будет продолжаться вечно.источник
.
для перемещения0
в строку исполнения требуется ведущий (или любой непробельный символ) .0000000...
как один целочисленный литерал, и строящаяся строка - это то, что продолжает занимать больше памяти. Программа, которая работает так же, как и этаa
(бесконечно толкает 10).Java 101 байт
Поймать основную программу в бесконечном цикле после создания и отбрасывания объекта. Сборка мусора выполняет утечку, создавая 2 объекта для каждого удаленного
источник
Perl, 12 байт
В Perl
x
оператор со строкой слева и числом справа создает повторяющуюся строку. Так"abc" x 3
оценивает"abcabcabc"
.x=
Оператор мутирует левый аргумент, заменяя содержимое переменной на ее слева, в результате повторения его содержание , как много раз , как его правая рука указывает.В Perl есть ряд встроенных переменных со странным именем, одна из которых
$"
, чье начальное значение - один пробел.redo
Оператор переходит к началу ограждающих{}
.В первый раз, когда
x=
оператор выполняется, он меняет значение$"
с" "
«на»" "
, что составляет 9 пробелов.Во второй раз, когда
x=
оператор выполняется, он меняет значение$"
на" "
, которое составляет 81 пробел.В третий раз
$"
получается строка длиной 729 байт.Я думаю, что вы можете видеть, куда это идет :).
источник
$_.=7
цикл, но я понял, что если бы я могx=
его использовать, мне бы хватило бы памяти, а затем побежал,perldoc perlvar
чтобы выбрать что-то подходящее.{$^O++;redo}
на один байт короче, когда^O
одинchr(15)
байт. Хотя он будет тратить память НАМНОГО медленнее - 1000000000 итераций требуются в Windows, чтобы тратить один байт. Будет работать на любой ОС, название которой начинается с латинской буквы.sed, 5 байт
Golfed
Использование (любой вход будет делать)
Разъяснения
Скриншот
Попробуйте онлайн!
источник
Haskell,
2319 байтовРаспечатать сумму бесконечного списка
источник
sum
определяется какfoldl (+) 0
, и что должно помешать анализу строгости, чтобы предотвратить выброс толчка? Вы запускали его с оптимизацией?sum
заранее не узнаю, что список бесконечен иprint
в сумме он должен быть оценен первым. И да, я скомпилировал его с оптимизациейInteger
по умолчанию числа не ограничены, и память, занятая текущим результатом bignum , действительно будет расти.sum xs = foldl (+) 0 xs
может выполняться в постоянном стеке, как любой императивный цикл .foldl' (+) 0 xs
конечно будет. Таким образом, единственное, что выделяет память наверняка, это промежуточный результат bignum.C ++ (с использованием компилятора g ++),
272315 байтСпасибо Neop за помощь в удалении 4 байтов
Это решение на самом деле не приводит к утечке памяти, поскольку оно выделяет все в стеке и, таким образом, вызывает переполнение стека. Это просто бесконечно рекурсивно. Каждая рекурсия вызывает выделение некоторой памяти до тех пор, пока стек не переполнится.
Альтернативное решение
Это решение на самом деле утечки памяти.
Выход Valgrind
Это вывод Valgrind после завершения программы через несколько секунд после запуска. Вы можете видеть, что это, безусловно, утечка памяти.
источник
int
пока я не увидел твои, так что спасибо!C++
, просто диалект g ++: C ++ запрещает вызывать main; C ++ требуетint main...
объявления. Но решение все еще опрятно :-)main
.ЯВА,
817978 байтJAVA (HotSpot)
7170 байтКороче, чем другие ответы Java на момент публикации (81, позднее 79 байт):
По предложению @Olivier Grégoire можно сохранить еще один байт:
Размещение
x+=x.intern()
в качестве приращения цикла for ничего не поможет, потому что точка с запятой все еще требуется для завершения оператора for.Как предлагает @ETHproductions,
x+=x
тоже просто работает работает:Который может также извлечь выгоду из подсказки @Olivier Grégoire:
Мое единственное опасение по этому поводу состоит в том, что не гарантируется выделение данных в куче , поскольку эффективная JVM может легко понять, что
x
никогда не ускользнет от локальной функции. Использованиеintern()
позволяет избежать этой проблемы, потому что интернированные строки в конечном итоге хранятся в статическом поле. Однако HotSpot генерируетOutOfMemoryError
для этого кода, так что я думаю, что все в порядке.Обновление: @Olivier Gregoire также отметил, что
x+=x
код может работать,StringIndexOutOfBoundsException
а неOOM
когда много памяти доступно. Это потому, что Java использует 32-битныйint
тип для индексации массивов (а строки - это просто массивыchar
). Это не влияет наx+=x.intern()
решение, так как память, необходимая для последнего, является квадратичной по длине строки и, следовательно, должна увеличиваться до порядка 2 ^ 62 выделенных байтов.источник
x+=x;
?x+=x.intern()
последнюю точку с запятой в цикле forintern
но я был очень счастлив с Unsafe и решил, что перестал искать, хаха. Первоначально этот вопрос указывал на «утечку памяти», поэтому я не просто ответил на строку.# Java (HotSpot), 71 bytes
). Таким образом, вам не нужно беспокоиться о возможном мошенничестве; специфичные для реализации программы распространены не только в гольфе, но и в более широком мире программирования, и если вы знаете, что делаете, иногда может быть более подходящим, чем портативная программа, скажем, для вне сценария.x+=x;
не исчерпывает всю память. С 64 ГБ я получаюStringIndexOutOfBoundsException
, а не ООМ. С.intern()
я все еще получаю OOM.Perl 6 , 13 байт
Объяснение:
@ =
сохранить результат в безымянный массивeager
сделать следующий список нетерпеливым0 .. *
бесконечный диапазон, начинающийся с нуляисточник
///, 7 байт
Постоянно заменить
a
сaa
, объявление тошноты.источник
aad naauseum
ad nauseam
=>aad naauseaam
//a/
? Это, кажется, навсегда заменит `` (ничто) наa
, но не уверен, точно ли это указано.Python 3, 16 байт
Это связано с тем, что в Python 3 нет ограничений на целочисленный размер; вместо этого целые числа могут занимать столько памяти, сколько может обработать система (если что-то в моем понимании этого неверно, исправьте меня).
источник
Ржавчина, 46 байт
Заметили что-нибудь интересное в этой программе Rust, утечка выделений кучи до нехватки памяти?
Это верно, нет небезопасного блока. Rust гарантирует безопасность памяти в безопасном коде (без чтения неинициализированных данных, чтения после освобождения, двойного освобождения и т. Д.), Но утечки памяти считаются совершенно безопасными. Есть даже явная функция, которая заставит компилятор забыть об очистке RAII от переменных вне области видимости, которые я здесь использую.
источник
TI-83 Hex Assembly, 7 байтов
Создает appvars бесконечно, пока
ERR:MEMORY
ОС не выбрасывает их. Беги сAsm(prgmM)
. Я считаю каждую пару шестнадцатеричных цифр одним байтом.источник
Python, 8 байт
О.П. позволило техничность программы , которая технически не запустить «навсегда», но выделяет больше памяти , чем любой компьютер мог справиться. Это не совсем googolplex (то есть
10**10**100
11 байт), но наивно, лог-база 2 числато есть, 10 ^ 94 бит, чтобы представить это. Вольфрам Альфа считает, что это на 10 ^ 76 больше, чем глубокая паутина (имейте в виду, что во вселенной около 10 ^ 80 атомов ).
Почему 2 вместо 9 ты спрашиваешь? Это не имеет большого значения (использование 9 увеличит количество битов только в два раза
log2(9) = 3.2
, что не изменит показатель степени). Но с другой стороны, программа работает намного быстрее с 2, так как расчет проще. Это означает, что он немедленно заполняет память, в отличие от версии 9, которая занимает немного больше времени из-за необходимых вычислений. Не обязательно, но приятно, если вы хотите «проверить» это (что я и сделал).источник
Желе ,
32 байта-1 байт благодаря Денису (
W
обертывания)Ссылка (то есть функция или метод), которая также работает как полная программа, которая рекурсивно оборачивает свои входные данные в список.
Входные данные начинаются с нуля, поэтому первый проход создает список.
[0]
Затем второй проход делает это
[[0]]
. Третий проход делает это
[[[0]]]
и так далее ...
Предыдущие 3 байта, которые протекают намного быстрее:
рекурсивно объединяет все непустые смежные подсписки своего ввода с его вводом.
[0]
->[0,[0]]
->[0,[0],[0],[[0]],[0,[0]]]
и так далее ...источник
‘ß
должно быть много.Wß
должен все же соответствовать счету все же.Java 7, 106 байт
Меньше гольфа
finalize
Метод вызывается для объекта сборщиком мусора , когда сборка мусора определяет , что больше нет ссылок на объект. Я просто переопределил этот метод, чтобы он зациклился навсегда, чтобы сборщик мусора никогда не освобождает память. Вmain
цикле я создаю новые объекты, которые никогда не будут очищены, поэтому в конечном итоге это израсходует всю доступную память.Java 7 (забавная альтернатива), 216 байт
Меньше гольфа
Это весело больше всего на свете. Этот ответ использует
Unsafe
библиотеку Sun, которая является недокументированным внутренним API. Возможно, вам придется изменить настройки компилятора, чтобы разрешить API с ограниченным доступом.Unsafe.allocateMemory
выделяет определенное количество байтов (без какой-либо проверки границ), которые не находятся в куче и не находятся под управлением java-сборщика мусора, поэтому эта память будет сохраняться до тех пор, пока вы не вызоветеUnsafe.freeMemory
или пока jvm не исчерпает памятьисточник
Haskell, 24 байта
Основная проблема в Haskell - победить лень.
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
и, следовательно, постоянно выделяет больше памяти.источник
f x=f x
тоже работает, верно? (-2 байта)f x=f x
создает бесконечный цикл, но без выделения новой памяти.f!x=x*f(x*x)
должен сделать это оптимизационным доказательством.постоянный ток, 7 байтов
[ddx]
толкает строку, содержащую «ddx» в стек.dx
дублирует его, затем выполняет его как код (оставляя одну копию в стеке). При выполнении он создает две копии, затем выполняет одну, оставляя еще одну копию в стеке каждый раз.источник
Haskell (использует ghc 8.0.1), 11 байт
Нехвостая рекурсия.
main
называет себя, а потом снова себя.источник
Stack space overflow: current size 33624 bytes.
33k кажется довольно низким в отличие от 6G общего объема памяти, о котором сообщает ОС.C (linux), 23 байта
sbrk()
увеличивает верхнюю часть сегмента данных на заданное количество байтов, тем самым эффективно увеличивая объем памяти, выделенной программе - по крайней мере, как указано вVIRT
полеtop
вывода. Это работает только в Linux - реализация macOS, по-видимому, является эмуляцией, которая позволяет выделять только до 4 МБ.Итак, немного более общий ответ:
C, 25 байтов
Я смотрел это на мониторе активности MacOS. До 48 ГБ, а затем процесс получил сигнал SIGKILL. FWIW мой MacBook Pro имеет 16 ГБ. Большая часть используемой памяти была сообщена как сжатая.
Обратите внимание, что этот вопрос фактически требует записи каждого выделения, что здесь явно не происходит. Однако важно отметить, что для каждого
malloc(9)
вызова выделяются не только 9 запрошенных пользователем байтов. Для каждого выделенного блока будет заголовок malloc, который также выделяется где-то в куче, что обязательно записываетсяmalloc()
внутренними компонентами.источник
malloc()
блок ed должен по-прежнему иметь свое собственное реальное выделенное пространство. Это работает на macOS и Ubuntu.main(){main(malloc(9));}
, но для того, чтобы не переполнять стек, требуется оптимизация хвостовых вызовов, и gcc, похоже, не хочет делать это наmain
...Perl, 4 байта
Выполняет себя в текущем интерпретаторе. По окончании выполнение возвращается к вызывающему сценарию, для которого требуется стек вызовов.
источник
Ракетка, 13 байт
Я не совсем уверен, подпадает ли мой ответ под этот вопрос. Пожалуйста, дайте мне знать, если я должен удалить этот ответ.
источник
l
как функция, которая выполняет рекурсию без вызова. Я бы сказал, что это имеет значение.JavaScript
2221171615 байтСохраните 4 байта, обернув список в другой список, как в ответе @Jonathan Allan's Jelly.
Сохранено 1 байт благодаря @ETHProductions
Альтернативное решение 15 байт (работает только с правильными оконечными вызовами)
источник
f=_=>f();f()
? 12 байтa=0
. Первая итерация приведет кa=[undefined]
Рубин, 11 байт
Продолжает нажимать
9
на$*
массив, который изначально содержит аргументы командной строки для процесса Ruby.источник
05AB1E , 2 байта
Попробуйте онлайн! Просто буду продолжать давить
abcdefghijklmnopqrstuvwyxz
на стек на вечность.Все возможные 2-байтовые решения:
источник
Python, 35 байт
a
никогда не выпускается и просто становится больше, пока вы не нажметеMemoryError
Вы можете посмотреть исполнение на Python Tutor .
источник
a+=a,
?TI-BASIC, 8
(все 1-байтовые токены и две строки)
Это постоянно приводит к утечке памяти, потому что структурированный поток управления, такой как
While
ожидаемое закрытие,End
и помещает что-то в стек (не в стек ОС, а в отдельный стек в кучной памяти), чтобы отслеживать это. Но здесь мы используем,Goto
чтобы выйти из цикла (так что noEnd
выполняется, чтобы удалить объект из стека),While
снова виден, объект снова перемещается и т. Д. Так что он просто продолжает нажимать их, пока вы не получитеERR:MEMORY
источник