В ознаменование публичного запуска Stack Overflow, какой самый короткий код вызывает переполнение стека? Любой язык приветствуется.
ETA: Чтобы прояснить этот вопрос, поскольку я время от времени пользуюсь схемой: "рекурсия" хвостового вызова на самом деле является итерацией, и любое решение, которое можно относительно легко преобразовать в итеративное решение с помощью приличного компилятора, не будет считаться. :-П
ETA2: Я выбрал «лучший ответ»; см. обоснование в эта почта. Спасибо всем, кто внес свой вклад! :-)





Мой текущий лучший результат (в сборке x86):
push eax
jmp short $-1
в результате получается 3 байта объектного кода (50 EB FD). Для 16-битного кода это тоже возможно:
call $
что также дает 3 байта (E8 FD FF).
Вопрос гласит: «[...] какой самый короткий код вызывает переполнение стека?» Он не указывает исходный код, интерпретируемый код, машинный код, объектный код или управляемый код ...
Для справки, сервер игры в гольф Шина позволяет вам отправлять объектный код для проверки, хотя он также будет считать все ваши заголовки ELF. Хм....
См., Например, golf.shinh.org/p.rb?FizzBuzz#x86 для некоторых примеров этого. (Я, честно говоря, не знаю, как люди могут создавать 99-байтовые двоичные файлы ELF.) :-P
@lbrandy: Есть достаточно людей, которые могут писать объектный код напрямую. Я не могу сделать это для x86, но для определенного микропроцессора могу. Я бы посчитал такой код.
C++:
int overflow(int n)
{
return overflow(1);
}
Хороший компилятор может оптимизировать его с помощью хвостового вызова! :-П
C#:
public int Foo { get { return Foo; } }
Python:
so=lambda:so();so()
Альтернативно:
def so():so()
so()
И если хвостовые вызовы, оптимизированные для Python ...:
o=lambda:map(o,o());o()
К счастью для вас, Python не выполняет оптимизацию хвостового вызова; в противном случае он был бы дисквалифицирован, как и два других ответа. :-П
PIC18:
overflow
PUSH CALL overflow
Очень мило, по духу похоже на мой ответ. Сколько байтов объектного кода он создает?
Честно говоря, я не совсем уверен!
int main(){
int a = 20;
return main();
}
Как и ответ Нияза, это также можно оптимизировать с помощью хвостового вызова!
Это недопустимый код, согласно C++ 98 3.6.1.3 «Функция main не должна использоваться в программе». </language_nazi>
JavaScript:
function i(){ i(); }
i();
int main(){
int (*f)() = &main;
f();
}
@danb, я пробовал это, но Rhino не хотел его компилировать.
новая функция i () {i ()} (); работает. все же не короче конечно ...
Как я прокомментировал в комментарии к сообщению Vulcan Eager, версия C++ недействительна, согласно C++ 98 3.6.1.3 «Функция main не должна использоваться в программе». </language_nazi>
@Motti: Позор Microsoft за то, что он скомпилировал его без ошибок в VS8 ;-)
@Huppie - рискну предположить, что это ошибка, не требующая диагностики, как и переполнение стека для начала. ! (компиляция кода -> код правильный).
По-английски:
recursion = n. See recursion.
Любой здравомыслящий человеческий мозг не взорвется, а оптимизирует интерпретацию и эту интерпретацию. :-П
Крис, разумный человеческий мозг в наши дни становится редкостью.
редкость ... вы имеете в виду, что они существуют?
Рекурсия Google
/* In C/C++ (second attempt) */
int main(){
int a = main() + 1;
return a;
}
Намного лучше! У меня тоже есть свой небольшой вклад. :-П
Кажется, это тоже можно оптимизировать. с gcc -O3 он просто запускается и запускается.
Прекрасно, Эндрю; он тоже был оптимизирован для прыжка!
ха-ха, в C++ вы не можете вызвать main или взять его адрес: p
@litb - вы говорите так, будто это выгода.
Вот мой вклад в C, весом 18 символов:
void o(){o();o();}
Это много сложнее оптимизировать с помощью хвостового вызова! :-П
Не компилируется для меня: "неопределенная ссылка на` main '": P
Я не понимаю: почему вызов () 2x?
@Dinah: Одним из ограничений моего конкурса было то, что оптимизация хвостового вызова не считается рекурсией; это просто итеративный цикл. Если вы написали o () только один раз, это можно оптимизировать с помощью хвостового вызова (с помощью компетентного компилятора): "o: jmp o". При двух вызовах o компилятор должен использовать что-то вроде: «o: call o; jmp o». Это рекурсивная инструкция «вызова» вызывает переполнение стека.
Вы правы - я не обратил внимания на эту часть. Спасибо за разъяснение.
C#, состоящий из 20 символов (без пробелов):
int s(){
return s();
}
Разве это не один из (небольшого) количества обстоятельств, когда компилятор .NET JIT может оптимизировать хвостовой вызов? :-П
Понятия не имею, но это разбило мой веб-сервер разработки :)
CIL / MSIL:
loop: ldc.i4.0
br loop
Код объекта:
16 2B FD
Хм, примет ли это верификатор .NET? Для JVM вы должны указать максимальное использование стека, и верификатор будет применять его, поэтому код, подобный приведенному выше (iconst_0; goto loop), будет отклонен.
Вы также можете попробовать это в C# .net
throw new StackOverflowException();
Педант во мне говорит, что это не вызывает переполнения стека, просто выдает исключение. Это как сказать, что самый быстрый способ подвергнуться нападению акул - это стоять в море и кричать «Атака акул!». Несмотря на это, я буду голосовать за него. :)
Ну а есть разница? Сможете ли вы поймать это и продолжить? Или это точно так же, как stackoverflow в C#? В этом случае это каким-то образом является stackoverflow, поскольку он неотличим от одного ... Однако - голосование по всем причинам, указанным выше
Если стек переполняется в лесу, и никто не может его поймать, генерирует ли это исключение?
Я бы не сказал «самый короткий», потому что вы не можете скомпилировать такой однострочный файл. Я думаю, что делает быстро вызывает переполнение стека.
Как насчет следующего в BASIC:
10 GOSUB 10
(Боюсь, у меня нет интерпретатора BASIC, так что это предположение).
Не совсем переполнение стека, поскольку BASIC - это язык без стека. Даже VB (у которого есть стек) не будет переполняться при этом, поскольку он просто прыгает, а не создает фрейм стека.
Это GOSUB, а не GOTO. Поскольку это RETURN, откуда он был вызван, наверняка он использует стек?
Да я согласен. У меня были переполнения стека много в BASIC в 80-х.
Я запустил это в yabasic просто для удовольствия, и он чуть не сломал мой компьютер. Слава богу, у malloc в конце концов не получилось, но я как будто не завтра.
Ой, извини, Адам ... напоминает мне время в универе, когда кто-то случайно написал программу, которая рекурсивно разветвлялась: уничтожала весь сервер Silicon Graphics.
Только что протестировал его на моем эмуляторе VZ200? ОШИБКА НЕТ ПАМЯТИ В 10
WTF кто нибудь делает с эмулятором VZ200? :-) Я не тоскую по своим старым ZX80 или COMX-35.
Nemerle:
Этот сбой компилятора с исключением StackOverflowException:
def o(){[o()]}
Рубин:
def s() s() end; s()
Вы называете себя рубиновым программистом ...? Вы можете сделать лучше: def s; s; end; s
Мне понравились кучи ответов Коди, так что вот мой аналогичный вклад на C++:
template <int i>
class Overflow {
typedef typename Overflow<i + 1>::type type;
};
typedef Overflow<0>::type Kaboom;
Ни в коем случае не кодовая запись в гольф, но все же что-нибудь для переполнения мета-стека! :-П
Лисп
(defun x() (x)) (x)
С некоторыми флагами компилятора это также можно оптимизировать с помощью хвостового вызова. :-)
В текущих реализациях Common Lisp вам придется явно декларировать или объявлять TCO. Схема даже требует ТШО. Чтобы сделать это гарантированно переполненным, не используйте хвостовую рекурсию: (defun x () (1+ (x))) (x).
a{return a*a;};
Скомпилировать с помощью:
gcc -D"a=main()" so.c
Расширяется до:
main() {
return main()*main();
}
Эх, по крайней мере, с Perl golf параметры командной строки учитываются при подсчете количества символов. :-П
OK 26 символов, включая параметр командной строки, для полностью компилируемой и запускаемой программы.
Хорошо, хорошо, я дам вам этот, так как вы хотели версию с main. :-)
C# снова:
class Foo { public Foo() {new Foo(); } }
Еще один отличный, продолжайте в том же духе!
Будет ли преобразование класса в структуру не использовать еще больше места в стеке, поскольку структура является типом значения?
perl в 12 символов:
$_=sub{&$_};&$_
bash в 10 символов (пробел в функции важен):
i(){ i;};i
Полная программа Delphi.
program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;
begin
raise EStackOverflow.Create('Stack Overflow');
end.
Ой, это смешно только один раз, и GateKiller уже получил такой ответ. :-П
Clarion:
Poke(0)
Есть ли общедоступная документация о том, как работает Clarion?
www.softvelocity.com содержит достаточно информации, а общедоступная группа новостей Clarion (comp.lang.clarion) обладает большим объемом информации и активным сообществом (хотя группа новостей на news.softvelocity.com является основной и не является t похоже обычно синхронизируются с другими серверами).
Ява (смущенно):
public class SO
{
private void killme()
{
killme();
}
public static void main(String[] args)
{
new SO().killme();
}
}
РЕДАКТИРОВАТЬ Конечно, его можно значительно сократить:
class SO
{
public static void main(String[] a)
{
main(null);
}
}
so.c в 15 персонажей:
main(){main();}
Результат:
antti@blah:~$ gcc so.c -o so
antti@blah:~$ ./so
Segmentation fault (core dumped)
Редактировать: Хорошо, он выдает предупреждения с -Wall и не вызывает переполнения стека с -O2. Но это работает!
Блеч! Это undefined, потому что у вас есть неявный возврат int без фактического возвращаемого значения. Если вы объявили main как void (по какой-то причине), тогда может применяться оптимизация хвостового вызова. Итак, нет. :-П
Я пробовал сделать это на Эрланге:
c(N)->c(N+1)+c(N-1).
c(0).
Двойной вызов самого себя приводит к увеличению использования памяти O(n^2), а не O(n).
Однако интерпретатор Erlang, похоже, не дает сбой.
Работает ли c (N) -> c (N + 1) + c (N + 1)?
JavaScript:
Гуппи отвечают на одну строчку:
(function i(){ i(); })()
Такое же количество символов, но без новой строки :)
Это отчасти умно, потому что отсутствие совокупной стоимости владения - известная «особенность» многих движков JavaScript.
+1 RangeError: Maximum call stack size exceeded
рекурсия - старая шляпа. вот взаимная рекурсия. начните с вызова любой функции.
a()
{
b();
}
b()
{
a();
}
PS: но вы просили кратчайший путь .. не самый творческий путь!
Какой это язык? Если это динамический язык, тогда можно применить оптимизацию хвостового вызова; если это C, и вы полагаетесь на неявное int, отсутствие возвращаемого значения является неопределенным поведением. Использование «return a ()» и «return b ()» также подлежит оптимизации хвостового вызова. :-П
Java (полное содержание X.java):
class X {
public static void main(String[] args) {
main(null);
}}
Учитывая весь синтаксический сахар, мне интересно, можно ли сделать что-то более короткое на Java. Кто угодно?
Обновлено: К сожалению, я пропустил, что уже опубликовано почти идентичное решение.
Обновлено еще раз: Я бы сказал, что это (по характеру) самый короткий из возможных
class X{public static void main(String[]a){main(null);}}
РЕДАКТИРОВАТЬ 3: Спасибо Андерсу за указание на то, что null не является оптимальным аргументом, поэтому его нужно делать короче:
class X{public static void main(String[]a){main(a);}}
class X {public static void main (String [] a) {main ("");}} короче ...;)
@Anders: "" instanceof String [] => false
Неа, короче сделал - смотри мой ответ.
На spus ячеек нет переполнения стека, поэтому нет необходимости в рекурсии, мы можем просто стереть указатель стека.
asm ("andi $ 1, $ 1, 0");
3 байта:
label:
pusha
jmp label
Обновлять
Согласно (старая?) документация Intel (?), это тоже 3 байта:
label:
call label
Это 3 байта в 32-битном режиме. Хороший ответ, учитывая, что он заполнит стек намного быстрее, чем мой ответ!
Согласно penguin.cz/~literakl/intel/j.html#JMP, jmp составляет 3 байта с 8, 16 или 32-битным относительным адресом назначения. Пуша также составляет 1 байт, что в сумме составляет 4
Есть три типа jmp: короткий, ближний и дальний. Короткий jmp (с использованием кода операции 0xEB) составляет два байта. Место назначения должно находиться на расстоянии от -128 до 127 байтов от следующей инструкции. :-)
Может быть, вы правы. Мне лень откопать свой ассемблер и проверить ...;)
PHP - рекурсия для развлечения. Я полагаю, что необходимость в интерпретаторе PHP исключит его из работы, но эй - он приведет к сбою.
function a() { a(); } a();
Perl уже был, но он на пару символов короче (9 против 12) - и он не рекурсивен :)
s//*_=0/e
Отлично! Это умно. Но в 5.10 это не работает: $> perl -e // * _ = 0 / e 'perl (30740) malloc: *** ошибка для объекта 0x301070: double free *** установить точку останова в malloc_error_break для отладки
Та же ошибка здесь, на моем Perl 5.8.8. :-(
Выход GWBASIC ...
OK
10 i=0
20 print i;
30 i=i+1
40 gosub 20
run
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
22 23 24 25 26 27 28 29 30 31 32 33
Out of memory in 30
Ok
Небольшая глубина стека :-)
//lang = C++... it's joke, of course
//Pay attention how
void StackOverflow(){printf("StackOverflow!");}
int main()
{
StackOverflow(); //called StackOverflow, right?
}
F#
Люди продолжают спрашивать: «Чем полезен F#?»
let rec f n =
f (n)
версия с оптимизацией производительности (быстрее выйдет из строя :))
let rec f n =
f (f(n))
Похоже, что не работает, у меня возникает ошибка «FS0030: ограничение значения».
Используйте их последнюю CTP, у меня работает :) также попробуйте f (f (n))
хм, возможно, это было исправлено в версии 1.9.6.0 -> 1.9.6.2, я думаю, тогда пойду проверю :-)
Первый хвостовой рекурсивный, второй будет работать, хотя
У меня есть их список на Бесконечный цикл на E2 - посмотрите только те, которые обозначены как «Переполнение стека» в заголовке.
Я думаю самый короткий есть
[dx]dx
в Округ Колумбия. В Ложь может быть более короткое решение.
Обновлено: По-видимому, это не работает ... По крайней мере, на GNU dc. Может быть, это была версия BSD.
Не работает. dc потребляет 100% ЦП, но не происходит переполнение стека в dc (GNU bc 1.06.94) 1.3.94. dc -e '[dx +] dx' делает ошибку сегментации.
Хм ... Я был уверен, что на какой-то версии работает. Это может быть только в некоторых версиях BSD.
Рубин:
def i()i()end;i()
(17 символов)
В Lua:
function f()return 1+f()end f()
Вы должны что-то сделать с результатом рекурсивного вызова, иначе оптимизация хвостового вызова позволит ему зацикливаться вечно. Слабый для кодового гольфа, но приятно иметь!
Я предполагаю, что это и длинные ключевые слова означают, что Lua в ближайшее время не выиграет кодовый гольф.
Ах. Вы побили мой (неопубликованный) результат. Я использовал f () * f (), чтобы избежать хвостового вызова.
Однако f () * f () неплохая идея: по-видимому (это больше не о Lua, кстати) GCC также может оптимизировать 1 + f () с хвостовым вызовом, при условии, что f () isn ' Я ожидал возвращения или что-то в этом роде. Подробнее см. Комментарии к №62221. :-П
пакетная программа call.cmd;
вызов call.cmd
****** B A T C H R E C U R S I O N exceeds STACK limits ******
Recursion Count=1240, Stack Usage=90 percent
****** B A T C H PROCESSING IS A B O R T E D ******
Perl в 10 символах
sub x{&x}x
В конце концов использует всю доступную память.
Пакет MS-DOS:
copy CON so.bat
so.bat
^Z
so.bat
Подожди, ты должен сказать «Позвони со.бат». Если я правильно помню, запуск командного файла без вызова похож на использование exec. :-П
Ява
Чуть более короткая версия Java-решения.
class X{public static void main(String[]a){main(a);}}
Или (такое же количество символов): public static void main (String ... a) {main ();}
Или для ребят из TDD (такое же количество символов): public class ${@org.junit.Test public void $ () {$ ();}}
Все еще не самый короткий (см. Мой ответ)
В Scheme это приведет к тому, что интерпретатору не хватит памяти:
(define (x)
((x)))
(x)
Решение сценария оболочки в 10 символов, включая новые строки:
Ну, технически это не переполнение стека, но логически это так, если вы рассматриваете создание нового процесса как создание нового кадра стека.
#!sh
./so
Результат:
antti@blah:~$ ./so
[disconnected]
Ой. Примечание: не пробуйте это дома
В Whitespace я думаю:
Вероятно, он не появится. : /
Браузеры не очень хорошо отображают вкладки, а Markdown полностью их стирает. Я вставлю то, что вижу (права редактирования для победы!), В свой следующий комментарий.
SP SP SP TAB NL NL SP SP SP TAB SP SP SP TAB TAB TAB NL TAB SP SP SP NL SP TAB SP TAB SP SP SP SP TAB TAB NL NL NL
C - не самый короткий, но без рекурсии. Он также не переносится: он дает сбой в Solaris, но некоторые реализации alloca () могут здесь возвращать ошибку (или вызывать malloc ()). Вызов printf () необходим.
#include <stdio.h>
#include <alloca.h>
#include <sys/resource.h>
int main(int argc, char *argv[]) {
struct rlimit rl = {0};
getrlimit(RLIMIT_STACK, &rl);
(void) alloca(rl.rlim_cur);
printf("Goodbye, world\n");
return 0;
}
Вы также можете просто выполнить "ulimit -s16", чтобы уменьшить размер стека. Любое меньше, чем примерно 16, и программа даже не запускается (очевидно, недостаточно аргументов!).
C# с 27 непробельными символами - включает вызов.
Action a = null;
a = () => a();
a();
xor esp, esp
ret
это не совсем переполнение стека, но это тоже хорошо: D
PowerShell
$f = {&$f};&$f
«Сценарий завершился неудачно из-за переполнения глубины вызова. Глубина вызова достигла 1001, а максимальное значение - 1000».
Прочтите эту строку и сделайте то, что в ней написано дважды.
bash: Только один процесс
\#!/bin/bash
of() { of; }
of
Руби, короче остальных пока:
def a;a;end;a
(13 символов)
Практически любая оболочка:
sh $0
(5 символов, работает только при запуске из файла)
ш $ 0 и ш $ 0; # сбой системы (остановите это с помощью kill -9-1 в другой оболочке от имени того же пользователя)
попробуйте положить более 4 пирожков на один бургер. переполнение стека.
Здесь, в Новой Зеландии, есть Burger Wisconsin, где используют большие, но тонкие котлеты. Я уверен, что вы можете сложить более 4 штук, если хотите; это будет очень дорогой бургер!
Может быть: alafista.com/2010/05/10/… Может быть, нет: cheaplightning.blogspot.com/2010/06/…
Ммм ... In-n-Out. en.wikipedia.org/wiki/In-n-out#Menu
Groovy:
main()
$ groovy stack.groovy:
Caught: java.lang.StackOverflowError
at stack.main(stack.groovy)
at stack.run(stack.groovy:1)
...
Проголосовали, потому что это довольно интересно. Однако обнаруживает довольно досадную слабость в компиляторе Groovy (такие хвостовые вызовы могут быть встроены во время компиляции).
ты уверен, что это хвост? что падение с конца программы не вызывает оболочку интерпретатора?
Пять байтов в 16-битном asm, что вызовет переполнение стека.
push cs
push $-1
ret
На ассемблере (процессоры x86, 16- или 32-разрядный режим):
call $
который будет генерировать:
в 32-битном режиме: 0xe8; 0xfb; 0xff; 0xff; 0xff
в 16-битном режиме: 0xe8; 0xfd; 0xff
в C / C++:
int main( ) {
return main( );
}
Ассемблер Z-80 - по адресу памяти 0x0000:
rst 00
один байт - 0xC7 - бесконечный цикл помещения текущего ПК в стек и перехода к адресу 0x0000.
Я помню, что пустой eprom будет содержать все 0xffs, которые являются первыми 7 (= вызов 0x0038) инструкциями. Это было бы полезно для отладки вашего оборудования с помощью осциллографа. Адресная шина будет циклически проходить через пространство 64 КБ, поскольку стек неоднократно переполнялся, перемежаясь с чтениями 0xff из 0x0038.
Javascript
Чтобы обрезать еще несколько символов и выгнать нас из большего количества магазинов программного обеспечения, давайте выберем:
eval(i='eval(i)');
Haskell:
let x = x
print x
Это не переполнение стека. let f x = f x >> x in f $ return()
Ну, никто еще не упомянул Coldfusion, так что ...
<cfinclude template = "#ListLast(CGI.SCRIPT_NAME, "/\")#">
Это должно сделать это.
VB.Net
Function StackOverflow() As Integer
Return StackOverflow()
End Function
При определенных условиях мне дают понять, что компилятор .NET JIT может оптимизировать его с помощью хвостового вызова!
TCL:
proc a {} a
У меня нет интерпретатора tclsh, который может выполнять хвостовую рекурсию, но это может обмануть такую вещь:
proc a {} "a;a"
Четвертый:
: a 1 recurse ; a
Внутри интерпретатора gforth:
: a 1 recurse ; a
*the terminal*:1: Return stack overflow
: a 1 recurse ; a
^
Backtrace:
На Power Mac G4 при приглашении Open Firmware машина просто зависает. :)
Ой, я не знаю, я никогда не писал код, который вызывает переполнение стека;)
Другой пример PHP:
<?
require(__FILE__);
Вы даже можете быть сокращены, пропустив круглые скобки (но добавив пробел вместо первого).
Ради интереса мне пришлось поискать сборку Motorola HC11:
org 0
Loop nop
jsr Loop
Хм, а HC11 не позволяет сразу jsr? Зачем нужен nop?
Твое право. Я просто ленился ;-) Слишком долго существовал на языках более высокого уровня. Пора вернуться к мелочам низкого уровня.
Пролог
п :-п.
= 5 символов
затем запустите его и запросите p
Я думаю, что это довольно мало и в прологе заканчивается стек.
запрос только переменной в прологе swi дает:
?- ИКС. % ... 1,000,000 ............ 10,000,000 лет спустя % % >> 42 << (последний выпуск дает вопрос)
и вот еще одна бомба вилки bash: : () {: |: &} ;:
Стек не иссякает, по крайней мере, в SWI-Prolog. Это хвостовая рекурсия. Что действительно исчерпывает стек, так это: «assert (p: - (p, q)), assert (q). P.»
как локальная переменная в функции C:
int x[100000000000];
Hex Закодируйте число, чтобы сократить это ...
Не очень коротко, но эффективно! (JavaScript)
setTimeout(1, function() {while(1) a=1;});
C#
class _{static void Main(){Main();}}
Обратите внимание, что моя программа - это компилируемая программа, а не просто одна функция. Я также удалил лишние пробелы.
Для чутья я сделал название класса как можно меньше.
Вы даже можете переименовать Main, если хотите, чтобы компилятор требовал специальной опции командной строки.
Все эти ответы и никакого Befunge? Я готов поспорить, что это самое короткое решение из всех:
1
Без шуток. Попробуйте сами: http://www.quirkster.com/iano/js/befunge.html
Обновлено: Я думаю, мне нужно объяснить это. Операнд 1 помещает 1 во внутренний стек Befunge, и отсутствие чего-либо еще помещает его в цикл по правилам языка.
Используя предоставленный интерпретатор, вы в конечном итоге - и я имею в виду в итоге - достигнете точки, когда массив Javascript, представляющий стек Befunge, станет слишком большим для перераспределения браузером. Если бы у вас был простой интерпретатор Befunge с меньшим и ограниченным стеком - как в случае с большинством языков ниже - эта программа быстрее вызвала бы более заметное переполнение.
Хм ... но это действительно переполнение стека или просто бесконечный цикл? Мой JS-интерпретатор сделал переполнение нет, просто ушел в отпуск, так сказать.
Это не бесконечный цикл, потому что инструкция 1 помещает 1 в стек. В конце концов, вашему интерпретатору Befunge не хватит места в стеке, но это займет некоторое время. :)
Вы ... разбили мой браузер и ... заставили мой вентилятор ЦП перегружаться.
Удивительный! Мой компьютер или браузер (Opera) не зависали, но оба процессора работали на 100%, а скорость вращения вентилятора была на 3.
Вот программа Befunge, которая переполняется быстрее: " Она загружает 79 копий числа 32 каждые два раза, а не 2 копии числа 1.
Если нет языка, в котором пустая программа вызывает переполнение стека, следующее должно быть кратчайшим из возможных.
Befunge:
:
Повторяет значение верхнего стека снова и снова.
редактировать: Патрика лучше. Заполнение стека единицами лучше, чем заполнение стека нулями, поскольку интерпретатор может оптимизировать размещение нулей в пустом стеке как бездействие.
Думаю, это жульничество, в которое я никогда раньше не играл;) но начнем
Ассемблер 8086:
org Int3VectorAdrress; это жульничество?
int 3
1 байт - или 5 символов, которые генерируют код, что вы скажете?
Хахаха, хорошая попытка. Я думаю, чтобы это сойти с рук, вам нужно сначала установить адрес вектора int 3 на что-то подходящее, и это тоже будет стоить вам некоторых байтов кода. :-П
Если вы рассматриваете кадр вызова как процесс, а стек как вашу машину Unix, вы можете рассматривать вилочную бомбу как программу параллельно для создания условия переполнения стека. Попробуйте этот 13-значный номер bash. Сохранение в файл не требуется.
:(){ :|:& };:
Руби, хоть и не такой короткий:
class Overflow
def initialize
Overflow.new
end
end
Overflow.new
TeX:
\def~{~.}~
Результаты в:
! TeX capacity exceeded, sorry [input stack size=5000].
~->~
.
~->~
.
~->~
.
~->~
.
~->~
.
~->~
.
...
<*> \def~{~.}~Латекс:
\end\end
Результаты в:
! TeX capacity exceeded, sorry [input stack size=5000].
\end #1->\csname end#1
\endcsname \@checkend {#1}\expandafter \endgroup \if@e...
<*> \end\endПоскольку ~ активен, его можно использовать вместо \a. И я обнаружил код LaTeX совершенно случайно. :)
Я думаю, что это будет работать на Java (не проверено):
enum A{B.values()}
enum B{A.values()}
Должно быть переполнение при статической инициализации до того, как произойдет сбой из-за отсутствия main (String []).
не будет самым коротким, но мне пришлось кое-что попробовать ... C#
строка [] f = новая строка [0]; Главный (f);
немного короче
static void Main(){Main();}
Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky);
Надеемся на отсутствие хвостовой рекурсии!
Хе-хе, смешно. Что касается разговоров, то идея «эффекта эхо-камеры» тоже весьма интересна. Не совсем вызывает переполнение стека, но все же.
Разве это не исключение с нулевым указателем? Извините, я знаю, что это шутка.
Использование командного файла Windows с именем "s.bat":
call s
В C# это создаст переполнение стека ...
static void Main()
{
Main();
}
почему нет
mov sp,0
(стек растет вниз)
В файле PostScript с именем so.ps вызовет execstackoverflow
%!PS
/increase {1 add} def
1 increase
(so.ps) run
Я думаю, вы хотели сказать это вместо этого: / recurse {1 recurse} def recurse
В Irssi (клиент IRC на основе терминала, а не «настоящий» язык программирования) $ L означает текущую командную строку. Таким образом, вы можете вызвать переполнение стека («достигнуть максимального предела рекурсии») с помощью:
/eval $L
Для каждой задачи нужен правильный инструмент. Встречайте язык ТАК переполнение, оптимизированный для переполнения стека:
so
Если вы создаете специализированный язык для генерации переполнений с минимальным количеством кода, очевидно, что вам нужно: (1) пустой ввод создает код переполнения стека (возможно, небольшой двоичный файл, который запускает собственный код, сгенерированный из записи кода сборки) или (2 ) все программы ввода создают указанный двоичный файл.
Хммм, не полный Тьюринг. Я пока не знаю, можно ли это назвать языком ...
Вот еще один ответ Ruby, в котором используются лямбды:
(a=lambda{a.call}).call
Мне потребовалась лишь доля секунды, чтобы получить «... 22730 уровней ...» в ошибке «Уровень стека слишком глубокий».
Я выбираю «лучший ответ» после этого поста. Но сначала я хотел бы поблагодарить за несколько очень оригинальных вкладов:
Как бы мне ни нравилось вышеизложенное, задача состоит в том, чтобы заниматься гольфом с кодами, и, чтобы быть справедливым по отношению к респондентам, я должен присудить «лучший ответ» на самый короткий код, которым является запись Befunge; Я не верю, что кто-то сможет победить это (хотя Конрад определенно пытался), поэтому поздравляю Патрика!
Увидев большое количество решений с переполнением стека за счет рекурсии, я удивлен, что никто (на момент написания) не поднял комбинатор Y (см. Эссе Дика Габриэля, Почему Y, для начинающих). У меня есть рекурсивное решение, использующее комбинатор Y, а также подход aku f (f (x)). :-)
((Y (lambda (f) (lambda (x) (f (f x))))) #f)
Еще один в JavaScript:
(function() { arguments.callee() })()
Хорошо, мне нравится этот, потому что, как и моя версия комбинатора Y, он не требует, чтобы вы давали имя функции. Хорошая вещь!
(function(){arguments.callee()})()
функция x () {x ()} x () -> 20; функция x () x (); x () -> 19, работает только в Firefox; Хорошая попытка жесткая; P (jk)
Vb6
Public Property Let x(ByVal y As Long)
x = y
End Property
Private Sub Class_Initialize()
x = 0
End Sub
Отлично. Похожая тема с одним из решений aku (за исключением того, что это было средство получения свойств, а здесь - средство установки свойств). +1!
Краткое решение на K&R C, может быть скомпилировано:
main(){main()}
14 байт
Вот еще один интересный из Scheme:
((lambda (x) (x x)) (lambda (x) (x x)))
Очень красиво, и в этом тоже есть хорошая симметрия. Кроме того, использовать формулировку (lambda (x) (x x)): ((Y (lambda (x) (x x))) #f) тоже очень весело!
О, это мило. Это работает и в Ruby, хотя и не так красиво, как в Scheme: lambda {| x | x.call x} .call лямбда {| x | x.call x}
ActionScript 3: Все сделано с массивами ...
var i=[];
i[i.push(i)]=i;
trace(i);
Может, не самый маленький, но я думаю, что он симпатичный. Особенно метод push, возвращающий новую длину массива!
Если вы замените trace(i); на console.info(i);, это также будет действительным кодом JavaScript в Chrome или Firefox с Firebug.
В ответ на комментарий комбинатора Y, я мог бы также использовать Y-комбинатор в исчислении SKI:
S (K (S I I)) (S (S (K S) K) (K (S I I)))
Я не знаю ни одного интерпретатора SKI, но однажды я написал графический интерпретатор примерно за час в ActionScript. Я был бы готов опубликовать, если есть интерес (хотя у меня никогда не было макета, работающего очень эффективно)
Прочтите все об этом здесь: http://en.wikipedia.org/wiki/SKI_combinator_calculus
В сборке x86 поместите команду деления на 0 в место в памяти обработчика прерывания для деления на 0!
Я считаю, что [это сообщение] (# 67749) использует те же концепции, но все равно хорошая попытка. :-)
Groovy (5B):
run()
в perl:
`$0`
Фактически, это будет работать с любой оболочкой, которая поддерживает синтаксис команды обратной кавычки и сохраняет свое собственное имя в $0.
Или, может быть, «сделать 0 долларов»? идет и пытается
Я собирался оставить ваш ответ в покое, однако вы редактировали его достаточно раз, чтобы я выступил. :-P Некоторые плакаты упомянули, что это больше переполнение таблицы процессов, чем переполнение стека как таковое. Некоторые люди также разместили в этой теме бомбы-вилки, которые могут вас заинтересовать. :-)
Ложь:
[1] [1] #
(False - это стековый язык: # - это цикл while, который принимает 2 замыкания, условное выражение и тело. Тело - это то, что вызывает переполнение).
CMD переполнение в одной строке
echo @call b.cmd > b.cmd & b
Пролог
При обращении к этой программе происходит сбой как SWI-Prolog, так и Sicstus Prolog.
p :- p, q.
:- p.
Redmond.Microsoft.Core.Windows.Start()
Результатом PIC18 ответ дан TK являются следующие инструкции (двоичные):
overflow
PUSH
0000 0000 0000 0101
CALL overflow
1110 1100 0000 0000
0000 0000 0000 0000
Однако только CALL выполнит переполнение стека:
CALL $
1110 1100 0000 0000
0000 0000 0000 0000
Но RCALL (относительный вызов) еще меньше (не глобальная память, поэтому нет необходимости в дополнительных 2 байтах):
RCALL $
1101 1000 0000 0000
Таким образом, наименьший размер на PIC18 - это одна инструкция, 16 бит (два байта). Это займет 2 цикла инструкций на цикл. При 4 тактовых циклах на цикл инструкций у вас есть 8 тактовых циклов. PIC18 имеет стек из 31 уровня, поэтому после 32-го цикла он переполняет стек за 256 тактов. На 64 МГц вы бы переполнить стек за 4 микросекунды и 2 байта.
Однако серия PIC16F5x использует 12-битные инструкции:
CALL $
1001 0000 0000
Опять же, два цикла команд на цикл, 4 такта на инструкцию, то есть 8 тактов на цикл.
Однако PIC16F5x имеет двухуровневый стек, поэтому в третьем цикле произойдет переполнение в 24 инструкции. На 20 МГц это будет переполнение за 1,2 микросекунды и 1,5 байта.
Intel 4004 имеет 8-битную инструкцию вызова подпрограммы:
CALL $
0101 0000
Для любопытных это соответствует ascii 'P'. С трехуровневым стеком, который занимает 24 тактовых цикла, всего 32,4 микросекунды и один байт. (Если вы не разгоните свой 4004 - давай, ты знаешь, что хочешь.)
Это так же мало, как и ответ befunge, но намного, намного быстрее, чем код befunge, работающий в текущих интерпретаторах.
Оптимизацию хвостового вызова можно саботировать, если он не хвостовой. В Common Lisp:
(defun f () (1+ (f)))
В Haskell
fix (1+)
Это пытается найти фиксированную точку функции (1+) (λ n → n + 1). Реализация исправления
fix f = (let x = f(x) in x)
Так
fix (1+)
становится
(1+) ((1+) ((1+) ...))
Обратите внимание, что
fix (+1)
просто петли.
Мета-проблема в D:
class C(int i) { C!(i+1) c; }
C!(1) c;
переполнение стека времени компиляции
_asm t: call t;
Лучшее решение lua:
function c()c()end;
Вставьте это в SciTE или в интерактивную командную строку и затем вызовите. Бум!
Скажите, пожалуйста, что означает аббревиатура «GNU».
Или Eine (Eine - это не Emacs), или Zwei (Zwei изначально был Eine). :-П
Или YAML, или WINE, или XNA, или что-то еще по адресу en.wikipedia.org/wiki/Recursive_acronym
Drei (Drei - это действительно Emacs Incognito), Fier (Fier - это Emacs Reinvented) - хорошо, я просто их придумал :-)
OCaml
let rec f l = f l@l;;
Этот немного другой. В стеке только один фрейм стека (так как он хвостовой рекурсивный), но его ввод продолжает расти, пока не переполнит стек. Просто вызовите f с непустым списком, например (в подсказке интерпретатора):
# f [0];;
Stack overflow during evaluation (looping recursion?).
Хотя на самом деле у него нет стека ...
brainf * ck 5 знаков
+[>+]
Язык ассемблера Z80 ...
.org 1000
loop: call loop
это генерирует 3 байта кода в ячейке 1000 ....
1000 CD 00 10
C#
class Program
{
class StackOverflowExceptionOverflow : System.Exception
{
public StackOverflowExceptionOverflow()
{
throw new StackOverflowExceptionOverflow();
}
}
static void Main(string[] args)
{
throw new StackOverflowExceptionOverflow();
}
}
Я понимаю, что это не самое короткое (и даже код в гольф, он не приблизился бы к короткому), но я просто не мог удержаться от выброса исключения, которое при вызове выдает исключение stackoverflowexception, прежде чем оно сможет завершить саму среду выполнения ^^
рубин (снова):
def a(x);x.gsub(/./){a$0};end;a"x"
Уже существует множество решений для Ruby, но я решил добавить регулярное выражение для хорошей меры.
{/}loop
При запуске в GhostScript выдает исключение:
GS>{/}loop
Error: /stackoverflow in --execute--
Operand stack:
--nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- %loop_continue 1753 2 3 %oparray_pop --nostringval-- --nostringval-- false 1 %stopped_push .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- %loop_continue
Dictionary stack:
--dict:1150/1684(ro)(G)-- --dict:0/20(G)-- --dict:70/200(L)--
Current allocation mode is local
Last OS error: 11
Current file position is 8
Вот рекурсивная версия без использования переменных (51 символ):
[{/[aload 8 1 roll]cvx exec}aload 8 1 roll]cvx exec
Другой командный файл Windows:
:a
@call :a
main(){
main();
}Простой и приятный C. Мне кажется, он интуитивно понятен.
GNU make:
Создайте файл "Makefile" со следующим содержимым:
a:
make
Затем запустите make:
$ make
Обратите внимание, что для смещения слова «make» необходимо использовать символ табуляции. Этот файл состоит из 9 символов, включая 2 символа конца строки и 1 символ табуляции.
Я полагаю, вы могли бы сделать то же самое с bash, но, вероятно, это слишком просто, чтобы быть интересным:
Создайте имя файла «b» и отметьте его как исполняемый (chmod + x b):
b ## ties the winning entry with only one character (does not require end-of-line)
Теперь запустите файл с
$ ( PATH=$PATH:. ; b )
Трудно сказать, приводит ли этот подход технически к переполнению стека, но он создает стек, который будет расти до тех пор, пока на машине не закончатся ресурсы. Самое интересное в том, чтобы сделать это с помощью GNU make, это то, что вы можете наблюдать, как он выводит информацию о статусе по мере сборки и уничтожения стека (при условии, что вы нажали ^ C в какой-то момент до того, как произойдет сбой).
Ява:
class X{static{new X();}{new X();}}
Фактически вызывает переполнение стека при инициализации класса X. Перед вызовом main () JVM должна загрузить класс, и при этом запускает любые анонимные статические блоки кода:
static {
new X();
}
Что, как видите, создает экземпляр X с помощью конструктора по умолчанию. JVM будет вызывать анонимные блоки кода еще до конструктора:
{
new X();
}
Это рекурсивная часть.
real n(0)
n(1)=0
end
или же
call main
end
Второй случай зависит от компилятора; для GNU Fortran его нужно будет скомпилировать с -fno-underscoring.
(Оба счетчика включают обязательные символы новой строки)
Ухать переполнение!
// v___v
let rec f o = f(o);(o)
// ['---']
// -"---"-
Haskell:
main = print $ x 1 where x y = x y + 1
Диалог АПЛ
fib←{
⍵∊0 1:⍵
+/∇¨⍵-1 2
}
int main(void) { return main(); }
Неудачно, ваш ответ может быть оптимизирован. :-P (Компилятор фактически превращает это в goto _main, где _main - глобальный символ, соответствующий вашей основной функции.)
PHP - рекурсивная аббревиатура
Python:
import sys
sys.setrecursionlimit(sys.maxint)
def so():
so()
so()
почему sys.maxint, просто установите его на 1, разбейте его быстрее ... и сохраните символы.
Если я установлюrecursionlimit (1), это вызовет RuntimeError, а не сбой.
Java: 35 символов
Думаю, уже поздно, но свою идею все равно выложу:
class A{{new A();}static{new A();}}
Использование функций статического инициализатора и инициализатора экземпляра.
Вот результат на моем компьютере (обратите внимание, что он показал два сообщения об ошибках):
Exception in thread "main" java.lang.StackOverflowError
at A.<init>(A.java:1)
......
at A.<init>(A.java:1)
Could not find the main class: A. Program will exit.
См. Также: http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/java/javaOO/initial.html
Хотя ваш ответ по-прежнему длиннее победного :-), это все еще довольно изящный подход, так что +1 вам!
Наконец я понял, что это сделал кто-то другой. Он примерно на средних страницах, где его очень трудно найти.
Что это за язык? GolfScript? :-)
eval(t = "eval(t)")
t = "Execute(t)":Execute(t)
template<int n>struct f{f<n+1>a;};f<0>::a;
выход:
$ g++ test.cpp;
test.cpp:1: error: template instantiation depth exceeds maximum of 500 (use -ftemplate-depth-NN to increase the maximum) instantiating ‘struct f<500>’
test.cpp:1: instantiated from ‘f<499>’
test.cpp:1: instantiated from ‘f<498>’
......
Даже если компилятор прошел через шаблон, будет следующая ошибка: отсутствует main.
Подсчет байтов после "компиляции" (или сборки) - это не кодовый гольф.