Как программист, вы наверняка знаете ошибку переполнения стека из-за очевидной рекурсии. Но, конечно, есть много странных и необычных способов заставить ваш любимый язык выплюнуть эту ошибку.
Цели:
- Должно вызывать переполнение стека, которое хорошо видно на выходе ошибки.
- Не допускается использование явной рекурсии.
Примеры неверных программ:
// Invalid, direct obvious recursion.
methodA(){ methodA(); }
// Invalid, indirect, but obvious recursion.
methodA(){ methodB(); }
methodB(){ methodA(); }
Самые креативные способы являются лучшими, так как это конкурс популярности . Т.е., избегайте скучных очевидных ответов, подобных этому:
throw new StackOverflowError(); // Valid, but very boring and downvote-deserving.
Несмотря на то, что я принял ответ сейчас, добавление дополнительных ответов все еще хорошо :)
popularity-contest
stack
masterX244
источник
источник
Ответы:
питон
Это приведет к немедленному отказу переводчика:
Вместо того, чтобы использовать рекурсию, он просто сжимает стек, поэтому он сразу переполнится.
источник
питон
источник
C / Linux 32bit
Работает путем перезаписи обратного адреса, поэтому
g
возвращается к точкеmain
до вызоваf
. Будет работать для любой платформы, где адреса возврата находятся в стеке, но могут потребоваться изменения.Конечно, запись вне массива - неопределенное поведение , и вы не можете гарантировать, что это вызовет переполнение стека, а не, скажем, раскрасит усы в синий цвет. Детали флагов платформы, компилятора и компиляции могут иметь большое значение.
источник
JavaScript / DOM
Если вы хотите убить свой браузер, попробуйте это в консоли.
источник
with (document.body) { addEventListener('DOMSubtreeModified', function() { appendChild(firstChild); }, false); title = 'Kill me!'; } 15:43:43.642 TypeError: can't convert undefined to object
Ява
Видел что-то вроде этого где-то здесь:
Изменить: нашел, где я видел это: ответ Джо К. на самую короткую программу, которая выдает ошибку StackOverflow
Это может запутать некоторых новичков в Java. Он просто скрывает рекурсивный вызов.
val + this
становитсяval + this.toString()
потому чтоval
это строка.Смотрите его здесь: http://ideone.com/Z0sXiD
источник
new StringBuilder().append(val).append("").append(this).toString()
, и последнее добавление вызывает String.valueOf (...), что, в свою очередь, вызывает toString. Это делает вашу трассировку стека немного разнообразной (там есть три метода)."" + this.toString()
.+ "" +
может спровоцировать людей, так как на первый взгляд это кажется бесполезным.String val;
иreturn val + this;
может быть немного хитрее""
время конструирования -String - это+ ""
С
Вполне легко:
источник
ulimit -s unlimited
в оболочке это решается в Linux)~0u
довольно большое число в C.Нерекурсивное переполнение стека в C
Соглашение о несоответствии.
Компилировать с
gcc -O0
.__cdecl
функции ожидают, что вызывающий объект очистит стек, и__stdcall
ожидают, что вызывающий объект сделает это, поэтому при вызове через указатель функции typecast очистка никогда не выполняется -main
помещает параметр в стек для каждого вызова, но ничего не выскакивает, и в конечном итоге стек заполняется.источник
JavaScript
источник
+this
?+{toString:"".toLocaleString}
:-)Я был разочарован тем фактом, что Java 7 и Java 8 невосприимчивы к моему злому коду в моем предыдущем ответе . Поэтому я решил, что для этого нужен патч.
Успех! Я сделал
printStackTrace()
бросокStackOverflowError
.printStackTrace()
обычно используется для отладки и регистрации, и никто не подозревает, что это может быть опасно. Нетрудно понять, что этот код может быть использован для создания серьезных проблем безопасности:Некоторые люди могут подумать, что это очевидная рекурсия. Это не так.
EvilException
Конструктор не вызываетgetCause()
метод, так что исключение на самом деле может быть выброшено благополучно в конце концов. ВызовgetCause()
метода не приведетStackOverflowError
ни к одному. Эта рекурсия находится внутри обычно неожиданногоprintStackTrace()
поведения JDK и любой сторонней библиотеки для отладки и ведения журнала, которые используются для проверки исключения. Кроме того, вполне вероятно, что место, где выдается исключение, очень далеко от места, где оно обрабатывается.Во всяком случае, вот код, который действительно генерирует a
StackOverflowError
и в конце концов не содержит рекурсивных вызовов методов.StackOverflowError
Происходит за пределамиmain
метода, в комплекте JDKUncaughtExceptionHandler
:источник
getCause()
метода не приводит кStackOverflowError
. Он основан на том факте, что существует код JDK, который рекурсивно вызываетgetCause()
метод.getCause
на just,return this;
но, очевидно, Java слишком умна для этого. Он замечает, что это "CIRCULAR REFERENCE
".StackOverflowError
потому что в пакете OpenBSD 5.5 jdk-1.7.0.21p2v0 есть ошибка. Это не бросаетStackOverflowError
. БьетSIGSEGV
и сбрасывает ядро.Linux x86 NASM Assembly
Спойлер:
источник
ret
C ++ во время компиляции
В этом исходном файле нет рекурсии, ни один из классов не является базовым, даже косвенно. (В C ++ в шаблонном классе, как этот,
S<1>
иS<2>
есть совершенно разные классы.) Ошибка сегментации происходит из-за переполнения стека после рекурсии в компиляторе.источник
template <typename T> auto foo(T t) -> decltype(foo(t)); decltype(foo(0)) x;
немного короче.Bash (Оповещение об опасности)
Строго говоря, это не приведет к прямому переполнению стека, но генерирует то, что может быть помечено как « ситуация генерирования постоянного стека- переполнения »: когда вы запускаете это, пока ваш диск не заполнен, и хотите удалить беспорядок с помощью «rm -rf» х ", тот поражен.
Это происходит не во всех системах. Некоторые из них более устойчивы, чем другие.
Большая опасность ВНИМАНИЕ:
некоторые системы справляются с этим очень плохо, и вам может быть очень трудно очистить (потому что сам «rm -rf» столкнется с проблемой повторного использования). Возможно, вам придется написать аналогичный скрипт для очистки.
Лучше попробуй это на виртуальной машине, если не уверен.
PS: то же самое относится, конечно, если запрограммировано или сделано в пакетном сценарии.
PPS: может быть интересно получить от вас комментарий, как ведет себя ваша конкретная система ...
источник
while cd x; do :; done; cd ..; while rmdir x; cd ..; done;
должно позаботиться об этом.Ява
Хороший из Java Puzzlers . Что это печатает?
Это фактически терпит неудачу с StackOverflowError.
Исключением в конструкторе является просто красная сельдь. Вот что говорит об этом книга:
источник
Латекс
Стек ввода переполняется, потому что
\end
многократно расширяется в бесконечном цикле, как описано здесь .TeX терпит неудачу с
TeX capacity exceeded, sorry [input stack size=5000]
или подобным.источник
BF
В конечном итоге переполнит стек, зависит только от того, как долго интерпретатор делает стек ...
источник
C #, во время компиляции
Есть несколько способов заставить компилятор Microsoft C # взорвать свой стек; всякий раз, когда вы видите «выражение слишком сложное, чтобы скомпилировать» ошибку компилятора C #, что почти наверняка потому, что стек перегорел.
Синтаксический анализатор имеет рекурсивное происхождение, поэтому любые достаточно глубоко вложенные языковые структуры будут уничтожать стек:
Анализатор выражений довольно умен в устранении рекурсий на стороне, которая обычно рекурсивна. Обычно:
который строит чрезвычайно глубокое дерево разбора, не взорвет стек. Но если вы заставите рекурсию произойти на другой стороне:
тогда стек может быть взорван.
У них есть неимоверное свойство, что программа очень большая. Также можно заставить семантический анализатор переходить в неограниченную рекурсию с помощью небольшой программы, потому что он недостаточно умен, чтобы удалять определенные странные циклы в системе типов. (Рослин может улучшить это.)
Я описываю, почему этот анализ переходит в бесконечную рекурсию здесь:
http://blogs.msdn.com/b/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx
и для многих других интересных примеров вы должны прочитать эту статью:
http://research.microsoft.com/en-us/um/people/akenn/generics/FOOL2007.pdf
источник
fatal error CS1647: An expression is too long or complex to compile near (code)
. Документация к этому сообщению об ошибке находится здесь , и это в точности так, как вы сказали: «Произошло переполнение стека в компиляторе, обрабатывающем ваш код».В интернете (используется миллиард человек / день)
Например, на веб-сайте поддержки Dell (без обид, простите Dell):
Если вы удалите тег поддержки из URL-адреса, он переходит в бесконечные перенаправления . В следующем URL-адресе ###### - любой тег поддержки.
http://www.dell.com/support/drivers/uk/en/ukdhs1/ServiceTag/######?s=BSD&~ck=mn
Я считаю, что это эквивалентно переполнению стека.
источник
/Errors/
к URL, а затем прекратит работу после получения HTTP 400 Bad Request. Но это, вероятно, способствует лучшему переполнению стека, чем бесконечное перенаправление.http://www.dell.com/support/drivers/uk/en/ukdhs1/ServiceTag/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/...
PHP
Переполнение стека выполняется только с элементами зацикливания.
Пояснение (наведите курсор на спойлер):
источник
while (1) { $a = array(&$a); }
или что-то подобное просто достигает предела памяти…Ява
Я сделал прямо противоположное - программа, которая, очевидно, должна выдавать ошибку переполнения стека, но это не так.
Подсказка: программа выполняется за O (2 n ) времени, а n - размер стека (обычно 1024).
Из Java Puzzlers # 45:
источник
finally
вместоcatch
, и время выполнения O (2 ^ n). Ответ обновлен.C #
Первый пост, поэтому, пожалуйста, будьте осторожны со мной.
Это просто создает трассировку стека, захватывает верхний кадр (который будет нашим последним вызовом
Main()
), получает метод и вызывает его.источник
Ява
printStackTrace()
вводится бесконечный цикл.printStackTrace()
выкидываетStackOverflowError
.Сумасшедшая вещь в том, что в Java 5 и 6 это не происходит из пользовательского кода, это происходит в коде JDK. Никто не разумно подозревает, что это
printStackTrace()
может быть опасно для выполнения.источник
InnerException
свойство доступно только для чтения и задается в конструкторе, поэтому для этого необходимо отражение.JavaScript: нерекурсивная, итерационная мутация функции
Здесь нет никакой рекурсии.
f
будет многократно каррироваться с большим количеством аргументов, пока не переполнит стек за один вызов функции.console.log
часть является необязательной, если вы хотите увидеть, сколько аргументов требуется для этого. Это также гарантирует, что умные движки JS не будут оптимизировать это.Код-версия для гольфа в CoffeeScript, 28 символов:
источник
C # с эпическим провалом
То, как это терпит неудачу, является эпическим, оно взорвало мой разум полностью:
Это всего лишь один кадр, казалось бы, бесконечной серии странных изображений.
Это должно быть самая странная вещь. Кто-нибудь может объяснить? По-видимому, все большее количество пробелов, используемых для отступов, приводит к появлению этих белых блоков. Это происходит на Win7 Enterprise x64 с .NET 4.5.
Я еще не видел конца этого. Если вы замените
System.Console.Out
наSystem.IO.Stream.Null
, он умирает довольно быстро.Объяснение довольно простое. Я делаю класс, который имеет единственное свойство, и он всегда возвращает новый экземпляр его содержащего типа. Так что это бесконечно глубокая иерархия объектов. Теперь нам нужно что-то, что пытается это прочитать. Вот где я использую то
XmlSerializer
, что делает именно это. И, видимо, он использует рекурсию.источник
удар
Хотя многие могут признать, что рекурсия очевидна , но она кажется красивой. Нет?
После выполнения вы гарантированно увидите:
источник
_(){_|_;};_
{
синтаксически правильного пробела ?):(){:|:;}:
Haskell
(грустно, но верно, по крайней мере
ghc-7.6
, хотя, сO1
или больше, это решит проблему)источник
sum
он реализован в терминахfoldl
, в которых используются хвостовые вызовы, но поскольку он не оценивает аккумулятор, он просто создает кучу блоков, размером с исходный список. Проблема исчезает при переключении наfoldl' (+)
, который строго оценивает и, таким образом, возвращает WHN в своем хвостовом вызове. Или, как я уже сказал, если вы включите оптимизацию GHC!Болтовня
Это создает новый метод на лету, который
создает новый метод на лету, который
создает новый метод на лету, который
...
...
..
и затем передает ему.
Дополнительная небольшая специя возникает из-за одновременной нагрузки на стековую память и кучную память путем создания более длинного и длинного имени метода и огромного числа в качестве получателя, когда мы падаем в дыру ... (но рекурсия поражает нас первой ).
скомпилировать в Integer:
затем перейдите, оценивая
"2 downTheRabbitHole"
...... через некоторое время, вы окажетесь в отладчике, показывая исключение RecursionException.
Затем вам нужно вычистить весь беспорядок (и SmallInteger, и LargeInteger теперь имеют много кода страны чудес):
или провести некоторое время в браузере, удаляя страну чудес Алисы.
Вот некоторые из главы следа:
PS: был добавлен «withoutUpdatingChangesFile:», чтобы избежать необходимости впоследствии очищать файл журнала изменений Smalltalk.
PPS: спасибо за вызов: думать о чем-то новом и инновационном было весело!
PPPS: Я хотел бы отметить, что некоторые диалекты / версии Smalltalk копируют переполненные стековые кадры в кучу - так что они могут столкнуться с нехваткой памяти.
источник
C #
Действительно большой
struct
, без рекурсии, чистый C #, небезопасный код.как кикер сбивает окна отладки, заявляя, что
{Cannot evaluate expression because the current thread is in a stack overflow state.}
И общая версия (спасибо за предложение NPSF3000)
источник
C #
Неправильная реализация переопределенного
==
оператора:Можно было бы сказать, что очевидно, что
operator==
вызывает себя с помощью==
оператора, но вы обычно об этом не думаете==
, поэтому легко попасть в эту ловушку.источник
Начало ответа с использованием SnakeYAML
Отредактируйте
Это до читателя, чтобы узнать, как это работает: P (tip: stackoverflow.com)
Кстати: рекурсия динамически выполняется SnakeYAML (вы заметите, если знаете, как он обнаруживает поля, которые он сериализует, и посмотрите в исходном коде России
Point
)Редактировать: рассказывая, как это работает:
SnakeYAML ищет пару
getXXX
иsetXXX
mthod с тем же именем,XXX
и тип возвращаемого значения получателя совпадает с параметром установщика; и удивительно, что уPoint
класса естьPoint getLocation()
иvoid setLocation(Point P)
который возвращает себя; SnakeYAML этого не замечает и повторяет эту причуду и StackOverflows. Обнаружил это, когда работал с ними внутриHashMap
и спрашивал об этом на stackoverflow.com.источник
C #
неправильно реализованный объект-получатель
источник
static void Main() { Main(); }
Main()
случайно. Но довольно просто случайно написать рекурсивное свойство, а затем перепутать его с переполнением стека.