Sebagai seorang programmer Anda tentu tahu kesalahan stack overflow karena rekursi yang jelas. Tetapi tentu saja ada banyak cara aneh dan tidak biasa untuk membuat bahasa favorit Anda meludahkan kesalahan itu.
Tujuan:
- Harus menyebabkan stack overflow yang terlihat jelas pada output kesalahan.
- Tidak diizinkan menggunakan rekursi yang jelas.
Contoh program yang tidak valid:
// Invalid, direct obvious recursion.
methodA(){ methodA(); }
// Invalid, indirect, but obvious recursion.
methodA(){ methodB(); }
methodB(){ methodA(); }
Cara paling kreatif adalah yang terbaik karena ini adalah kontes popularitas . Yaitu, hindari jawaban jelas yang membosankan seperti ini:
throw new StackOverflowError(); // Valid, but very boring and downvote-deserving.
Meskipun saya menerima jawaban sekarang, menambahkan lebih banyak jawaban masih oke :)
popularity-contest
stack
masterX244
sumber
sumber
Jawaban:
Python
Ini akan menyebabkan penerjemah segera gagal:
Alih-alih menggunakan rekursi, itu hanya menyusut tumpukan sehingga akan langsung meluap.
sumber
Python
sumber
C / Linux 32bit
Bekerja dengan menimpa alamat pengirim, Jadi
g
kembali ke titikmain
sebelum meneleponf
. Akan bekerja untuk platform apa pun di mana alamat pengirim berada di tumpukan, tetapi mungkin memerlukan penyesuaian.Tentu saja, menulis di luar array adalah perilaku yang tidak terdefinisi , dan Anda tidak memiliki jaminan bahwa itu akan menyebabkan stack overflow daripada, katakanlah, cat biru kumis Anda. Detail platform, compiler dan flag kompilasi dapat membuat perbedaan besar.
sumber
JavaScript / DOM
Jika Anda ingin mematikan peramban, cobalah di konsol.
sumber
with (document.body) { addEventListener('DOMSubtreeModified', function() { appendChild(firstChild); }, false); title = 'Kill me!'; } 15:43:43.642 TypeError: can't convert undefined to object
Jawa
Melihat sesuatu seperti ini di sekitar sini:
Sunting: Ditemukan di tempat saya melihatnya: Jawaban Joe K untuk program terpendek yang melempar Kesalahan StackOverflow
Itu bisa membingungkan beberapa pemula Java. Itu hanya menyembunyikan panggilan rekursif.
val + this
menjadival + this.toString()
karenaval
adalah sebuah String.Lihat dijalankan di sini: http://ideone.com/Z0sXiD
sumber
new StringBuilder().append(val).append("").append(this).toString()
, dan append terakhir memanggil String.valueOf (...), yang pada gilirannya memanggil toString. Ini membuat jejak Stack Anda sedikit bervariasi (tiga metode di sana)."" + this.toString()
.+ "" +
mungkin tip orang, karena terlihat tidak berguna pada pandangan pertama.String val;
danreturn val + this;
mungkin sedikit sneakier""
konstruksi -String adalah dengan+ ""
C
Cukup mudah:
sumber
ulimit -s unlimited
shell menyelesaikan ini di linux)~0u
adalah angka yang cukup besar di C.Stack overflow non-rekursif dalam C
Ketidakcocokan konvensi panggilan.
Kompilasi dengan
gcc -O0
.__cdecl
fungsi mengharapkan penelepon untuk membersihkan tumpukan, dan__stdcall
mengharapkan callee untuk melakukannya, jadi dengan memanggil melalui pointer fungsi typecast, pembersihan tidak pernah dilakukan -main
mendorong parameter ke tumpukan untuk setiap panggilan tetapi tidak ada yang muncul dan akhirnya tumpukan mengisi.sumber
JavaScript
sumber
+this
harus dilakukan+{toString:"".toLocaleString}
:-)Saya frustrasi dengan fakta bahwa java 7 dan java 8 kebal terhadap kode jahat saya di jawaban saya sebelumnya . Jadi saya memutuskan bahwa tambalan untuk itu perlu.
Keberhasilan! Saya membuat
printStackTrace()
lemparanStackOverflowError
.printStackTrace()
biasanya digunakan untuk debugging dan logging dan tidak ada yang mencurigai itu bisa berbahaya. Tidak sulit untuk melihat bahwa kode ini dapat disalahgunakan untuk menciptakan beberapa masalah keamanan serius:Beberapa orang mungkin berpikir bahwa ini adalah rekursi yang jelas. Bukan itu. The
EvilException
konstruktor tidak menyebutgetCause()
metode, sehingga pengecualian yang benar-benar dapat dibuang dengan aman setelah semua. MemanggilgetCause()
metode tidak akan menghasilkan yangStackOverflowError
baik. Rekursi ini ada di dalamprintStackTrace()
perilaku JDK yang biasanya tidak terduga dan pustaka pihak ketiga apa pun untuk debugging dan logging yang digunakan untuk memeriksa pengecualian. Lebih lanjut, kemungkinan tempat pengecualian dibuang sangat jauh dari tempat penanganannya.Lagi pula, ini adalah kode yang melempar
StackOverflowError
dan tidak mengandung panggilan metode rekursif. TheStackOverflowError
terjadi di luarmain
metode, di JDKUncaughtExceptionHandler
:sumber
getCause()
metode tidak menghasilkanStackOverflowError
. Itu bergantung pada fakta bahwa ada kode JDK yang secara rekursif memanggilgetCause()
metode.getCause
menjadi hanyareturn this;
tetapi ternyata Java terlalu pintar untuk itu. Itu memperhatikan bahwa itu adalah "CIRCULAR REFERENCE
".StackOverflowError
karena paket OpenBSD 5.5 dari jdk-1.7.0.21p2v0 memiliki bug. Itu tidak melemparStackOverflowError
. MemukulSIGSEGV
dan membuang inti.Linux x86 NASM Assembly
Spoiler:
sumber
ret
C ++ pada waktu kompilasi
Tidak ada rekursi file sumber ini, tidak satu pun dari kelas itu sendiri sebagai kelas dasar, bahkan tidak secara tidak langsung. (Dalam C ++, dalam kelas templat seperti ini,
S<1>
danS<2>
merupakan kelas yang benar-benar berbeda.) Kesalahan segmentasi adalah karena stack overflow setelah rekursi dalam kompiler.sumber
template <typename T> auto foo(T t) -> decltype(foo(t)); decltype(foo(0)) x;
sedikit lebih pendek.Bash (Peringatan Bahaya)
Sebenarnya, itu tidak akan secara langsung menumpuk overflow, tetapi menghasilkan apa yang mungkin diberi label sebagai " situasi menghasilkan stack-over-flow persisten ": ketika Anda menjalankan ini sampai disk Anda penuh, dan ingin menghapus kekacauan dengan "rm -rf x ", yang itu kena.
Itu tidak terjadi pada semua sistem. Beberapa lebih kuat dari yang lain.
Bahaya besar PERINGATAN:
beberapa sistem menangani hal ini dengan sangat buruk dan Anda mungkin mengalami kesulitan membersihkan (karena "rm-rf" itu sendiri akan mengalami masalah resusi). Anda mungkin harus menulis skrip yang mirip dengan pembersihan.
Lebih baik coba ini di VM awal jika tidak yakin.
PS: hal yang sama berlaku, tentu saja, jika diprogram atau dilakukan dalam skrip batch.
PPS: mungkin interresting untuk mendapatkan komentar dari Anda, bagaimana sistem khusus Anda berperilaku ...
sumber
while cd x; do :; done; cd ..; while rmdir x; cd ..; done;
harus mengurus ini.Jawa
Yang bagus dari Java Puzzlers . Apa yang dicetak?
Ini sebenarnya gagal dengan StackOverflowError.
Pengecualian dalam konstruktor hanyalah herring merah. Inilah yang dikatakan buku tentangnya:
sumber
Getah
Tumpukan input meluap karena
\end
berulang kali mengembang dengan sendirinya dalam loop tak terbatas, seperti dijelaskan di sini .TeX gagal dengan
TeX capacity exceeded, sorry [input stack size=5000]
atau serupa.sumber
BF
Akhirnya akan meluap tumpukan, hanya tergantung berapa lama penerjemah membuat ...
sumber
C #, pada waktu kompilasi
Ada beberapa cara untuk menyebabkan kompiler Microsoft C # memuntahkan tumpukannya; setiap kali Anda melihat kesalahan "ekspresi terlalu rumit untuk dikompilasi" dari kompiler C # yang hampir pasti karena tumpukan telah meledak.
Parser adalah turunan rekursif, sehingga setiap struktur bahasa yang cukup bersarang akan meniup stack:
Pengurai ekspresi cukup pintar untuk menghilangkan rekursi pada sisi yang biasanya berulang. Biasanya:
yang membangun pohon parse yang sangat dalam, tidak akan meniup tumpukan. Tetapi jika Anda memaksa rekursi terjadi di sisi lain:
maka tumpukan bisa ditiup.
Ini memiliki properti tidak elegan bahwa program ini sangat besar. Dimungkinkan juga untuk membuat penganalisis semantik melakukan rekursi tak terbatas dengan program kecil karena tidak cukup pintar untuk menghilangkan siklus aneh tertentu dalam sistem tipe. (Roslyn mungkin memperbaiki ini.)
Saya menjelaskan mengapa analisis ini masuk ke rekursi tak terbatas di sini:
http://blogs.msdn.com/b/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx
dan untuk banyak contoh menarik lainnya Anda harus membaca makalah ini:
http://research.microsoft.com/en-us/um/people/akenn/generics/FOOL2007.pdf
sumber
fatal error CS1647: An expression is too long or complex to compile near (code)
. Dokumentasi untuk pesan kesalahan ini ada di sini , dan persis seperti yang Anda katakan: "Ada stack overflow di kompiler yang memproses kode Anda."Di Internet (digunakan oleh miliar orang / hari)
Misalnya, di situs web dukungan Dell (jangan tersinggung, maaf Dell):
Jika Anda menghapus TAG dukungan dari URL, maka masuk ke pengalihan tak terbatas . Di URL berikut, ###### adalah TAG dukungan.
http://www.dell.com/support/drivers/uk/en/ukdhs1/ServiceTag/######?s=BSD&~ck=mn
Saya percaya itu setara dengan stack overflow.
sumber
/Errors/
ke URL dan kemudian berhenti setelah menerima Permintaan Buruk HTTP 400. Tapi ini bisa dibilang membuat stack overflow lebih baik daripada redirect yang tidak terbatas.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
Alur stackover dilakukan dengan elemen pengulangan saja.
Penjelasan (arahkan kursor untuk melihat spoiler):
sumber
while (1) { $a = array(&$a); }
atau sesuatu yang serupa hanya mencapai batas memori ...Jawa
Saya melakukan yang sebaliknya - sebuah program yang jelas harus membuang kesalahan stack overflow, tetapi tidak.
Petunjuk: program berjalan dalam waktu O (2 n ), dan n adalah ukuran tumpukan (biasanya 1024).
Dari Java Puzzlers # 45:
sumber
finally
daripadacatch
, dan waktu berjalan adalah O (2 ^ n). Jawaban diperbarui.C #
Posting pertama, jadi tolong mudahkan saya.
Ini hanya membuat jejak stack, meraih frame atas (yang akan menjadi panggilan terakhir kami
Main()
), mendapatkan metode, dan memanggilnya.sumber
Jawa
printStackTrace()
memasuki loop tak terbatas.printStackTrace()
melemparStackOverflowError
.Yang gila adalah bahwa di Java 5 dan 6, itu tidak berasal dari kode pengguna, itu terjadi dalam kode JDK. Tidak ada satu pun tersangka masuk akal yang
printStackTrace()
bisa berbahaya untuk dieksekusi.sumber
InnerException
properti hanya-baca dan diatur dalam konstruktor, sehingga refleksi diperlukan untuk menyebabkan ini.JavaScript: Mutasi fungsi berulang, non-rekursif
Tidak ada rekursi di sini sama sekali.
f
akan berulang kali dijilat dengan lebih banyak argumen hingga dapat meluap tumpukan dalam satu panggilan fungsi. Bagianconsole.log
ini opsional jika Anda ingin melihat berapa banyak argumen yang diperlukan untuk melakukannya. Ini juga memastikan bahwa mesin JS pintar tidak akan mengoptimalkan ini.Versi kode-golf dalam CoffeeScript, 28 karakter:
sumber
C # dengan epik gagal
Cara itu gagal adalah epik, itu benar-benar mengejutkan saya:
Ini hanya satu bingkai dari serangkaian gambar aneh yang tampaknya tak terbatas.
Ini pasti hal yang paling aneh. Adakah yang bisa menjelaskan? Rupanya, semakin banyak ruang yang digunakan untuk lekukan menyebabkan blok putih itu muncul. Ini terjadi pada Win7 Enterprise x64 dengan .NET 4.5.
Saya belum benar-benar melihat akhirnya. Jika Anda ganti
System.Console.Out
denganSystem.IO.Stream.Null
, itu mati cukup cepat.Penjelasannya cukup sederhana. Saya membuat kelas yang memiliki properti tunggal, dan selalu mengembalikan instance baru dari tipe yang berisi. Jadi itu adalah hierarki objek yang sangat jauh. Sekarang kita perlu sesuatu yang mencoba untuk membacanya. Di situlah saya menggunakan
XmlSerializer
, yang tidak hanya itu. Dan ternyata, ia menggunakan rekursi.sumber
pesta
Meskipun banyak yang mungkin menyadari bahwa rekursi sudah jelas , tetapi tampaknya cukup. Tidak?
Setelah eksekusi, Anda dijamin melihat:
sumber
_(){_|_;};_
{
benar secara sintaksis?):(){:|:;}:
Haskell
(sedih tapi benar sampai setidaknya
ghc-7.6
, meskipun denganO1
atau lebih itu akan mengoptimalkan masalah menjauh)sumber
sum
diimplementasikan dalam halfoldl
, yang memang menggunakan panggilan ekor, tetapi karena tidak mengevaluasi akumulator hanya semata-mata menghasilkan setumpuk thunks sebesar daftar asli. Masalahnya menghilang ketika beralih kefoldl' (+)
, yang mengevaluasi secara ketat dan dengan demikian mengembalikan WHN dalam panggilan ekornya. Atau, seperti yang saya katakan, jika Anda mengaktifkan optimisasi GHC!Smalltalk
Ini menciptakan metode baru dengan cepat, yang
menciptakan metode baru dengan cepat, yang
menciptakan metode baru dengan cepat, yang
...
...
..
dan kemudian mentransfernya.
Rempah-rempah kecil tambahan berasal dari menekankan memori stack dan menumpuk memori pada saat yang sama, dengan menciptakan nama metode yang lebih lama dan lebih lama, dan sejumlah besar sebagai penerima, saat kita jatuh ke lubang ... (tetapi rekursi menghantam kita lebih dulu ).
kompilasi dalam Integer:
lalu lompat, dengan mengevaluasi
"2 downTheRabbitHole"
...... setelah beberapa saat, Anda akan berakhir di debugger, menampilkan RecursionException.
Maka Anda harus membersihkan semua kekacauan (SmallInteger dan LargeInteger sekarang memiliki banyak kode wonderland):
atau menghabiskan waktu di browser, menghapus wonderland alice.
Berikut ini beberapa dari kepala jejak:
PS: the "withoutUpdatingChangesFile:" ditambahkan untuk menghindari keharusan membersihkan file perubahan-log Smalltalk yang persisten sesudahnya.
PPS: terima kasih atas tantangannya: memikirkan sesuatu yang baru dan inovatif itu menyenangkan!
PPPS: Saya ingin mencatat bahwa beberapa dialek / versi Smalltalk menyalin frame stack yang meluap ke tumpukan - jadi ini mungkin malah menjadi situasi kehabisan memori.
sumber
C #
Sangat besar
struct
, tanpa rekursi, C # murni, bukan kode tidak aman.sebagai kicker itu crash windows debug yang menyatakan itu
{Cannot evaluate expression because the current thread is in a stack overflow state.}
Dan versi generik (terima kasih atas saran NPSF3000)
sumber
C #
Kesalahan implementasi
==
operator utama:Orang mungkin mengatakan itu jelas yang
operator==
menyebut dirinya dengan menggunakan==
operator, tetapi Anda biasanya tidak berpikir seperti itu==
, sehingga mudah untuk jatuh ke dalam perangkap itu.sumber
Mulai balas menggunakan SnakeYAML
Edit: ungolfed itu
Terserah pembaca untuk mengetahui cara kerjanya: P (tip: stackoverflow.com)
Omong-omong: rekursi dibuat secara dinamis oleh SnakeYAML (Anda akan melihat jika Anda tahu cara mendeteksi bidang yang diserialisasi dan melihatnya dalam
Point
kode sumber)Sunting: memberi tahu cara kerjanya:
SnakeYAML mencari sepasang
getXXX
dansetXXX
mthod dengan nama yang sama untukXXX
dan mengembalikan tipe pengambil sama dengan parameter setter; dan yang mengejutkan,Point
kelas memilikiPoint getLocation()
danvoid setLocation(Point P)
yang mengembalikan sendiri; SnakeYAML tidak menyadarinya dan muncul kembali pada kekhasan dan aliran StackOver itu. Menemukan yang ketika bekerja dengan mereka di dalamHashMap
dan bertanya pada stackoverflow.com di atasnya.sumber
C #
pengambil properti yang diimplementasikan dengan salah
sumber
static void Main() { Main(); }
Main()
tidak sengaja. Tetapi cukup sederhana untuk menulis properti rekursif secara tidak sengaja dan kemudian dikacaukan oleh stack overflow.