Cara teraneh untuk menghasilkan stack overflow [ditutup]

146

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:

  1. Harus menyebabkan stack overflow yang terlihat jelas pada output kesalahan.
  2. 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 . 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 :)

masterX244
sumber
14
Saya cenderung menghasilkan dengan menavigasi ke stackoverflow.com, meskipun saya telah dikenal untuk menanyakan 'stack overflow' di mesin pencari pilihan saya.
OJFord
21
Gunakan Internet Explorer. Cara yang pasti untuk menangkap satu :)
asgoth
64
Cara paling aneh untuk menghasilkan stack overflow adalah dengan memposting kontes popularitas di codegolf.stackexchange.com meminta orang untuk memposting cara paling aneh untuk menghasilkan stack overflow. Para responden, dalam menguji solusi mereka untuk pertanyaan itu, akan menghasilkan stack overflow. Saya belum mengujinya, jadi saya tidak yakin itu berhasil (itulah sebabnya saya tidak mempostingnya sebagai jawaban).
Tim Seguine
3
Saya mendukung
robert
11
Mengendarai Toyota (Hei, tunggu sebentar, mobil saya adalah Toyota ...)
squeamish ossifrage

Jawaban:

224

Python

import sys
sys.setrecursionlimit(1)

Ini akan menyebabkan penerjemah segera gagal:

$ cat test.py
import sys
sys.setrecursionlimit(1)
$ python test.py
Exception RuntimeError: 'maximum recursion depth exceeded' in <function _remove at 0x10e947b18> ignored
Exception RuntimeError: 'maximum recursion depth exceeded' in <function _remove at 0x10e8f6050> ignored
$ 

Alih-alih menggunakan rekursi, itu hanya menyusut tumpukan sehingga akan langsung meluap.

marinus
sumber
12
Lucu, tapi tidak seperti apa tujuan pertanyaan awal menurut saya.
Nit
12
@Nit, saya tidak melihat masalah. Bagaimana dengan solusi ini yang tidak memuaskan?
SimonT
17
@ masterX244 Ya, inti pertanyaannya adalah "jangan lakukan itu dengan cara biasa".
Plutor
24
@Putor apakah Anda biasanya membuat StackOverFlow dengan sengaja?
Kiwy
15
Ini hanya sedikit pintar saat pertama kali diposting .
Primo
189

Python

import webbrowser
webbrowser.open("http://stackoverflow.com/")
Dokter
sumber
7
Fantastis. Bagus dan elegan.
James Webster
103
Banyak literal. Jawabannya sangat.
Tim Seguine
47
Yah, ini menunjukkan Stack Overflow, tetapi untuk menghasilkan satu, ini hanya berfungsi jika itu Jeff Atwood atau Joel Spolsky yang mengeksekusinya.
Siput mekanik
10
@TimSeguine Wow.
Sean Allred
9
Bukan jawaban karena tidak ada dalam output kesalahan.
Pierre Arlaud
131

C / Linux 32bit

void g(void *p){
        void *a[1];
        a[2]=p-5;
}
void f(){
        void *a[1];
        g(a[2]);
}
main(){
        f();
        return 0;
}

Bekerja dengan menimpa alamat pengirim, Jadi gkembali ke titik mainsebelum menelepon f. 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.

ugoren
sumber
1
Bukankah ini menghasilkan segfault?
11684
4
+1 untuk manipulasi tumpukan aneh dan sama sekali tidak ada rekursi!
RSFalcon7
6
@ 11684, Ini perilaku yang tidak terdefinisi, jadi secara umum bisa crash. Pada 32bit Linux (yang saya uji), ia menulis di luar array, menimpa alamat pengirim, dan tidak mogok sampai stack meluap.
ugoren
46
"Lukis biru kumismu" -> kalimat itu membuatku.
Aneesh Dogra
2
Wow. Ini sangat mengaburkan.
MirroredFate
108

JavaScript / DOM

with (document.body) {
    addEventListener('DOMSubtreeModified', function() {
        appendChild(firstChild);
    }, false);

    title = 'Kill me!';
}

Jika Anda ingin mematikan peramban, cobalah di konsol.

Penglihatan
sumber
53
Saya yakin Anda berhak mendapatkan lebih banyak +1 suara, tetapi sayangnya orang-orang mencoba ini sebelum memberikan suara .... lol
Reactgular
5
Ya, itu efektif. Saya bahkan tidak bisa membuat task manager saya terbuka untuk membunuhnya.
Primo
1
Gunakan Chrome, tutup tab. Masalah terpecahkan.
Cole Johnson
1
with (document.body) { addEventListener('DOMSubtreeModified', function() { appendChild(firstChild); }, false); title = 'Kill me!'; } 15:43:43.642 TypeError: can't convert undefined to object
Brian Minton
1
Damn My Firefox digantung
Farhad
91

Jawa

Melihat sesuatu seperti ini di sekitar sini:

Sunting: Ditemukan di tempat saya melihatnya: Jawaban Joe K untuk program terpendek yang melempar Kesalahan StackOverflow

public class A {
    String val;
    public String toString() {
        return val + this;
    }

    public static void main(String[] args) {
        System.out.println(new A());
    }
}

Itu bisa membingungkan beberapa pemula Java. Itu hanya menyembunyikan panggilan rekursif. val + thismenjadi val + this.toString()karena valadalah sebuah String.

Lihat dijalankan di sini: http://ideone.com/Z0sXiD

Justin
sumber
30
Sebenarnya, itu benar 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).
Paŭlo Ebermann
2
@ PaŭloEbermann Ya, itu benar. Namun, jauh lebih mudah untuk mengatakannya "" + this.toString().
Justin
2
Saya pikir + "" +mungkin tip orang, karena terlihat tidak berguna pada pandangan pertama. String val;dan return val + this;mungkin sedikit sneakier
Cruncher
@Cruncher tidak sama sekali. Jika Anda seorang Java coder, Anda akan tahu bahwa cara mudah menggabungkan suatu int ke string selama ""konstruksi -String adalah dengan+ ""
Justin
5
Dalam aplikasi dunia nyata saya lebih suka menghindari rekursi tak terbatas dan menumpuk kesalahan overflow
jon_darkstar
77

C

Cukup mudah:

int main()
{
    int large[10000000] = {0};
    return 0;
}
Shahbaz
sumber
10
+1 untuk yang tidak jelas! Meskipun sangat bergantung pada sistem (sebuah ulimit -s unlimitedshell menyelesaikan ini di linux)
RSFalcon7
4
@ RSFalcon7, terima kasih untuk +1, tetapi bagi saya ini sebenarnya yang paling jelas !!
Shahbaz
14
@Cruncher: Itu tidak menghasilkan rekursi. Masalah yang diberikan adalah untuk meniup stack. Pada banyak sistem operasi, stack memiliki ukuran tetap, dan jauh lebih kecil dari sepuluh juta int, jadi ini akan menghancurkan stack.
Eric Lippert
2
@HannoBinder, Di Linux tempat saya diuji, Anda tidak mendapatkan kesalahan stack overflow. Anda mendapatkan kesalahan segmentasi, karena meluapnya tumpukan menghasilkan akses ke segmen yang tidak dimiliki. Saya tidak yakin apakah stack overflow error bahkan ada di Linux, karena pemanggilan fungsi rekursif tak terbatas juga memberikan kesalahan segmentasi.
Shahbaz
3
~0uadalah angka yang cukup besar di C.
Vortico
63

Stack overflow non-rekursif dalam C

Ketidakcocokan konvensi panggilan.

typedef void __stdcall (* ptr) (int);

void __cdecl hello (int x) { }

void main () {
  ptr goodbye = (ptr)&hello;
  while (1) 
    goodbye(0);
}

Kompilasi dengan gcc -O0.

__cdeclfungsi mengharapkan penelepon untuk membersihkan tumpukan, dan __stdcallmengharapkan callee untuk melakukannya, jadi dengan memanggil melalui pointer fungsi typecast, pembersihan tidak pernah dilakukan - mainmendorong parameter ke tumpukan untuk setiap panggilan tetapi tidak ada yang muncul dan akhirnya tumpukan mengisi.

Jason C
sumber
2
cara yang bagus untuk mengirim spam ke tumpukan: P
masterX244
62

JavaScript

window.toString = String.toLocaleString;
+this;
Ryan Cavanaugh
sumber
5
Yang ini kurang dihargai.
Ry-
1
Apa yang +thisharus dilakukan
NobleUplift
8
Unary + memanggil operasi abstrak ToNumber. Itu menggunakan operasi ToPrimitive dengan jenis nomor petunjuk. ToPrimitive pada Obyek menggunakan metode internal [[DefaultValue]], yang ketika melewati petunjuk angka, pertama-tama memeriksa untuk melihat apakah metode valueOf () ada dan mengembalikan primitif. window.valueOf () mengembalikan objek, jadi alih-alih [[Nilai Default]] mengembalikan hasil pemanggilan toString (). Window.toString hal pertama tidak (sekarang toLocaleString) dipanggil toString pada 'ini'. Ulangi.
Ryan Cavanaugh
3
Jika Chrome melakukan kesalahan, 'Terlalu banyak rekursi', maka Chrome akan berfungsi dengan baik, bukan? Stack overflow, dan itulah cara Chrome memberikan pengecualian overflow stack.
David Conrad
4
Anda harus menggunakan +{toString:"".toLocaleString}:-)
Bergi
62

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()lemparan StackOverflowError. 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:

public class StillMoreEvilThanMyPreviousOne {
    public static void main(String[] args) {
        try {
            evilMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void evilMethod() throws Exception {
        throw new EvilException();
    }

    public static class EvilException extends Exception {
        @Override
        public Throwable getCause() {
            return new EvilException();
        }
    }
}

Beberapa orang mungkin berpikir bahwa ini adalah rekursi yang jelas. Bukan itu. The EvilExceptionkonstruktor tidak menyebut getCause()metode, sehingga pengecualian yang benar-benar dapat dibuang dengan aman setelah semua. Memanggil getCause()metode tidak akan menghasilkan yang StackOverflowErrorbaik. Rekursi ini ada di dalam printStackTrace()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 StackOverflowErrordan tidak mengandung panggilan metode rekursif. The StackOverflowErrorterjadi di luar mainmetode, di JDK UncaughtExceptionHandler:

public class StillMoreEvilThanMyPreviousOneVersion2 {
    public static void main(String[] args) {
        evilMethod();
    }

    private static void evilMethod() {
        throw new EvilException();
    }

    public static class EvilException extends RuntimeException {
        @Override
        public Throwable getCause() {
            return new EvilException();
        }
    }
}
Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"
Victor Stafusa
sumber
2
: D dan sekarang dengan metode yang sesuai versi cross java stackoverflow. Bajingan jahat! : D
Kiwy
9
Saya cenderung menganggap rekursi dalam kasus ini jelas.
Taemyr
1
@ BlacklightShining Memanggil getCause()metode tidak menghasilkan StackOverflowError. Itu bergantung pada fakta bahwa ada kode JDK yang secara rekursif memanggil getCause()metode.
Victor Stafusa
2
Saya pikir Anda bisa menyederhanakan ini dengan mengubah tubuh getCausemenjadi hanya return this;tetapi ternyata Java terlalu pintar untuk itu. Itu memperhatikan bahwa itu adalah " CIRCULAR REFERENCE".
David Conrad
1
Saya tidak mendapatkan StackOverflowErrorkarena paket OpenBSD 5.5 dari jdk-1.7.0.21p2v0 memiliki bug. Itu tidak melempar StackOverflowError. Memukul SIGSEGVdan membuang inti.
kernigh
57

Linux x86 NASM Assembly

section .data
    helloStr:     db 'Hello world!',10 ; Define our string
    helloStrLen:  equ $-helloStr       ; Define the length of our string

section .text
    global _start

    doExit:
        mov eax,1 ; Exit is syscall 1
        mov ebx,0 ; Exit status for success
        int 80h   ; Execute syscall

    printHello:
        mov eax,4           ; Write syscall is No. 4
        mov ebx,1           ; File descriptor 1, stdout
        mov ecx,helloStr    ; Our hello string
        mov edx,helloStrLen ; The length of our hello string
        int 80h             ; execute the syscall

    _start:
        call printHello ; Print "Hello World!" once
        call doExit     ; Exit afterwards

Spoiler:

Lupa untuk kembali dari printHello, jadi kami langsung menuju _start lagi.

Michael Ehrenreich
sumber
78
Dalam pertemuan, tidak ada yang jelas.
11684
21
@ 11684: Saya menemukan yang sebaliknya benar: dalam perakitan, semuanya jelas karena tidak ada yang bisa menggunakan abstraksi untuk menyembunyikan apa yang sebenarnya dilakukan kode mereka.
Mason Wheeler
3
Ini brilian karena kesederhanaan dan keanggunannya.
haneefmubarak
11
@MasonWheeler: Saya lebih suka mengatakan bahwa semuanya terlihat daripada jelas ... Untuk cara yang baik untuk melihat perbedaan antara terlihat dan jelas, saya suka merujuk ke underhanded.xcott.com
Olivier Dulac
2
Saya ingat kesalahan saya yang sering luparet
Ruslan
48

C ++ pada waktu kompilasi

template <unsigned N>
struct S : S<N-1> {};

template <>
struct S<0> {};

template
struct S<-1>;
$ g ++ -c test.cc -ftemplate-depth = 40000
g ++: kesalahan kompiler internal: Kesalahan segmentasi (program cc1plus)
Silakan kirim laporan bug lengkap,
dengan sumber yang telah diproses jika perlu.
Lihat instruksi.

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>dan S<2>merupakan kelas yang benar-benar berbeda.) Kesalahan segmentasi adalah karena stack overflow setelah rekursi dalam kompiler.

hvd
sumber
7
Saya akui saya akan menyebutnya rekursi yang jelas dalam program metap Anda.
2
GCC mendeteksi rekursi dan berhenti dengan anggun di sisi ini (4,8 dan di atasnya tampaknya baik-baik saja)
Alec Teal
2
template <typename T> auto foo(T t) -> decltype(foo(t)); decltype(foo(0)) x;sedikit lebih pendek.
Casey
2
@ Hvd Tampaknya mengeksploitasi bug di GCC. Dentang menangkap penggunaan yang salah - yang saya anggap sudah Anda sadari - tapi itu membuat GCC saya memuntahkan hampir 2 megabyte pesan kesalahan.
Casey
4
+1 untuk meta stack overflow : p
Aschratt
45

Bash (Peringatan Bahaya)

while true
do 
  mkdir x
  cd x
done

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

blabla999
sumber
seperti yang saya tulis: pada banyak sistem, rm -rf mencoba untuk turun dan dipukul oleh satu (mungkin tidak lagi, hari ini, dengan ruang alamat 64bit - tetapi pada mesin yang lebih kecil dengan tumpukan yang lebih kecil, mungkin). Tentu saja, mungkin ada "implementasi" di sekitar, yang melakukannya secara berbeda ...
blabla999
2
Menurut saya sesuatu seperti while cd x; do :; done; cd ..; while rmdir x; cd ..; done;harus mengurus ini.
Blacklight Shining
Anda benar sekali (itulah yang saya maksudkan dengan "skrip serupa untuk pembersihan"). Namun, setelah disk Anda (atau kuota) penuh, Anda bahkan mungkin mengalami kesulitan masuk setelahnya, karena beberapa sistem digunakan untuk menangani situasi itu dengan buruk. Anda harus masuk sebagai root dan melakukan skrip (yang mudah pada PC-PC saat ini, tetapi seringkali sulit di zaman kuno, ketika komputer di mana digunakan oleh lebih dari satu pengguna).
blabla999
lucu, ini mendapat lebih banyak suara daripada sihir Smalltalk di bawah ini (tidak pernah terpikirkan!)
blabla999
seseorang mencoba ini di Windows?
Sarge Borsch
43

Jawa

Yang bagus dari Java Puzzlers . Apa yang dicetak?

public class Reluctant {
    private Reluctant internalInstance = new Reluctant();

    public Reluctant() throws Exception {
        throw new Exception("I'm not coming out");
    }

    public static void main(String[] args) {
        try {
            Reluctant b = new Reluctant();
            System.out.println("Surprise!");
        } catch (Exception ex) {
            System.out.println("I told you so");
        }
    }
}

Ini sebenarnya gagal dengan StackOverflowError.

Pengecualian dalam konstruktor hanyalah herring merah. Inilah yang dikatakan buku tentangnya:

Ketika Anda memanggil konstruktor, inisialisasi variabel instan dijalankan sebelum badan konstruktor . Dalam hal ini, penginisialisasi untuk variabel internalInstancememanggil konstruktor secara rekursif. Konstruktor itu, pada gilirannya, menginisialisasi bidangnya sendiri internalInstancedengan memanggil konstruktor Reluctant lagi dan seterusnya, ad infinitum. Doa rekursif ini menyebabkan StackOverflowErrorsebelum tubuh konstruktor pernah mendapat kesempatan untuk mengeksekusi. Karena StackOverflowErrormerupakan subtipe Errordaripada Exception, klausa catch in maintidak menangkapnya.

ntoskrnl
sumber
41

Getah

\end\end

Tumpukan input meluap karena \endberulang 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.

bwDraco
sumber
1
Saya sedang menunggu masalah TeX / LaTeX. Hal-hal itu lebih menggelegar daripada kebanyakan - biasanya, saya lupa bahwa apa yang saya lakukan dianggap sebagai pemrograman ketika tiba-tiba saya berhasil menulis sesuatu yang sangat rekursif.
Ernir
1
"Kapasitas TeX terlampaui, maaf" TeX sangat sopan ketika gagal.
Alex A.
40

BF

Akhirnya akan meluap tumpukan, hanya tergantung berapa lama penerjemah membuat ...

+[>+]
Timtech
sumber
5
Kode itu mengingatkan saya pada permainan kehidupan.
Adam Arold
10
Sebenarnya, tidak ada tumpukan di brainfuck.
fejesjoco
6
@fejesjoco Tape, jika Anda mau.
Timtech
32

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:

 class C { class C { class C { ....

Pengurai ekspresi cukup pintar untuk menghilangkan rekursi pada sisi yang biasanya berulang. Biasanya:

x = 1 + 1 + 1 + 1 + .... + 1;

yang membangun pohon parse yang sangat dalam, tidak akan meniup tumpukan. Tetapi jika Anda memaksa rekursi terjadi di sisi lain:

x = 1 + (1 + (1 + (1 + ....+ (1 + 1))))))))))))))))))))))))))))))))))))))))))...;

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.)

public interface IN<in U> {}
public interface IC<X> : IN<IN<IC<IC<X>>>> {}
...
IC<double> bar = whatever;
IN<IC<string>> foo = bar;  // Is this assignment legal? 

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

Eric Lippert
sumber
2
Pesan kesalahan sebenarnya adalah 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."
bwDraco
32

Di Internet (digunakan oleh miliar orang / hari)

Redirects, HTTP status code: 301

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.

codeSetter
sumber
5
cara yang bagus :) firefox mengatakan bahwa ia dialihkan sehingga permintaan tidak dapat diselesaikan yang merupakan stackoverflow rquivalent :)
masterX244
3
Perhatikan bahwa arahan ulang tidak terbatas - jika Anda menekan "Coba Lagi" itu menambahkan beberapa lagi /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.
nandhp
@nandhp, saya setuju, tetapi jika Anda berpikir peramban dunia ketiga (bukan modern, IE dll.), Mereka belum mendapatkan petunjuk tentang situasi ini.
codeSetter
2
Begini cara Wget merespons di sini: pastebin.com/pPRktM1m
bwDraco
1
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/...
Vortico
31

PHP

Alur stackover dilakukan dengan elemen pengulangan saja.

$a = array(&$a);
while (1) {
    foreach ($a as &$tmp) {
        $tmp = array($tmp, &$a);
    }
}

Penjelasan (arahkan kursor untuk melihat spoiler):

Program ini akan melakukan segmentasi ketika penerjemah mencoba untuk sampah mengumpulkan $tmparray pergi (ketika menugaskan kembali di $tmpsini). Hanya karena array terlalu dalam (referensi sendiri) dan kemudian pengumpul sampah berakhir dalam rekursi.

bwoebi
sumber
16
PHP PHP tidak dapat mendeteksi struktur referensi-diri? Benarkah?! Aduh. Itu adalah jahat.
Peter C
1
Ya, tapi itu tidak sempurna. Ada beberapa alasan mengapa while (1) { $a = array(&$a); }atau sesuatu yang serupa hanya mencapai batas memori ...
bwoebi
yup, saya pikir itu alasan yang sama mengapa PHP tidak bekerja dengan benar mengenai pengembangan Object Oriented juga; (abstraksi, warisan, dll.)
pythonian29033
1
@ pythonian29033 peduli untuk menjelaskan?
vvondra
30

Jawa

Saya melakukan yang sebaliknya - sebuah program yang jelas harus membuang kesalahan stack overflow, tetapi tidak.

public class Evil {
    public static void main(String[] args) {
        recurse();
    }

    private static void recurse() {
        try {
            recurse();
        } finally {
            recurse();
        }
    }
}

Petunjuk: program berjalan dalam waktu O (2 n ), dan n adalah ukuran tumpukan (biasanya 1024).

Dari Java Puzzlers # 45:

Mari kita asumsikan bahwa mesin kami dapat mengeksekusi 10 10 panggilan per detik dan menghasilkan 10 10 pengecualian per detik, yang cukup murah hati dengan standar saat ini. Berdasarkan asumsi ini, program ini akan berakhir sekitar 1,7 × 10 291 tahun. Untuk menempatkan ini dalam perspektif, umur matahari kita diperkirakan 10 10 tahun, jadi itu adalah taruhan yang aman bahwa tidak seorang pun dari kita akan ada untuk melihat program ini berakhir. Meskipun ini bukan loop tak terbatas, mungkin juga demikian.

ntoskrnl
sumber
3
Rekursi yang jelas ... tidak terlalu menarik.
Kami
5
@Kami Sudahkah Anda mencobanya? Apakah Anda benar-benar mendapatkan StackOverflowError? Tampaknya jelas, tetapi tidak.
ntoskrnl
Hanya karena pengecualian tertangkap bukan berarti itu tidak pernah dilempar. Program ini melempar pengecualian stack overflow setelah waktu O (n)
CodesInChaos
1
@CodesInChaos Oke, jadi saya memeriksa ulang ini, dan versi yang benar menggunakan finallydaripada catch, dan waktu berjalan adalah O (2 ^ n). Jawaban diperbarui.
ntoskrnl
@tidak bagus +1 memberi +1; btw punya compiler ke stackoverflow sudah (compiler berjalan di dalam VM, juga fyi)
masterX244
30

C #

Posting pertama, jadi tolong mudahkan saya.

class Program
{
    static void Main()
    {
        new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Invoke(null, null);
    }
}

Ini hanya membuat jejak stack, meraih frame atas (yang akan menjadi panggilan terakhir kami Main()), mendapatkan metode, dan memanggilnya.

BenM
sumber
cara yang bagus untuk selfvvoke yang tidak jelas tanpa menjelaskan; Memberi +1
masterX244
Anda harus mengomentari kode itu dengan "apa yang mungkin salah?": P
Spaceman
26

Jawa

  • Di Java 5, printStackTrace()memasuki loop tak terbatas.
  • Di Jawa 6, printStackTrace()melempar StackOverflowError.
  • Di Java 7 dan 8, sudah diperbaiki.

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.

public class Bad {
    public static void main(String[] args) {
        try {
            evilMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void evilMethod() throws Exception {
        Exception a = new Exception();
        Exception b = new Exception(a);
        a.initCause(b);
        throw a;
    }
}
Victor Stafusa
sumber
7
ya; stackoverflows dari ketiadaan adalah teman terbaik untuk codetrolling dan sakit kepala yang serius dalam berburu mereka
masterX244
2
Jika ada yang bertanya-tanya, kode setara dalam C # menyebabkan loop tak terbatas. Tetapi InnerExceptionproperti hanya-baca dan diatur dalam konstruktor, sehingga refleksi diperlukan untuk menyebabkan ini.
Athari
17

JavaScript: Mutasi fungsi berulang, non-rekursif

var f = function() {
    console.log(arguments.length);
};

while (true) {
    f = f.bind(null, 1);
    f();
}

Tidak ada rekursi di sini sama sekali. fakan berulang kali dijilat dengan lebih banyak argumen hingga dapat meluap tumpukan dalam satu panggilan fungsi. Bagian console.logini 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:

f=->
do f=f.bind f,1 while 1
Justin Morgan
sumber
14

C # dengan epik gagal

using System.Xml.Serialization;

[XmlRoot]
public class P
{
    public P X { get { return new P(); } set { } }
    static void Main()
    {
        new XmlSerializer(typeof(P)).Serialize(System.Console.Out, new P());
    }
}

Cara itu gagal adalah epik, itu benar-benar mengejutkan saya:

masukkan deskripsi gambar di sini

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.Outdengan System.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.

fejesjoco
sumber
ya; serialisasi ftw: P; tetapi yang lebih lucu adalah ketika Anda benar-benar di luar kode Anda seperti bagaimana snakeyaml mendapatkan atribut dan satu kelas mengembalikan dirinya dengan cara yang berulang berulang
masterX244
1
Nah, overflow itu terjadi di luar kode saya, tetapi alasan sebenarnya saya memposting ini adalah karena efek samping yang tidak terduga di konsol :-)
fejesjoco
Saya pikir bit putih harus ada hubungannya dengan. Net 4.5 atau bagaimana lingkungan Anda diatur, karena menggunakan. Net 4 (bahkan ketika dijalankan melalui cmd) saya hanya mendapatkan spasi, tidak ada blok putih. Dugaan saya adalah bahwa versi Win7 Enterprise cmd atau emulator konsol .Net 4.5 memperlakukan kombinasi karakter tertentu sebagai 'ubah latar belakang warna konsol'.
Pharap
Saya tidak dapat mereproduksinya dengan .NET 4.5 pada Win7 x64 Professional dengan Aero dihidupkan
Ray
Juga tidak dapat mereproduksi. .NET 4.5, Windows 8.1 Pro.
bwDraco
13

pesta

_(){ _;};_

Meskipun banyak yang mungkin menyadari bahwa rekursi sudah jelas , tetapi tampaknya cukup. Tidak?

Setelah eksekusi, Anda dijamin melihat:

Segmentation fault (core dumped)
devnull
sumber
5
yang ini lebih cantik dan lebih buruk:_(){_|_;};_
RSFalcon7
1
@ RSFalcon7 Forkbomb waspada! (Juga, bukankah itu membutuhkan ruang setelah {benar secara sintaksis?)
Blacklight Shining
3
Coba ini juga:(){:|:;}:
Tarek Eldeeb
14
Tampak seperti emotikon mutan yang menyeramkan.
Tim Seguine
8
Bash emotikon: pemakan wajah, pembunuh tumpukan.
NobleUplift
12

Haskell

(sedih tapi benar sampai setidaknya ghc-7.6, meskipun dengan O1atau lebih itu akan mengoptimalkan masalah menjauh)

main = print $ sum [1 .. 100000000]
berhenti mengubah counterclockwis
sumber
bukankah seharusnya melakukan pengoptimalan panggilan ekor secara otomatis (jumlah)?
blabla999
2
@ blabla999: panggilan ekor tidak begitu relevan di Haskell, itu sebagian besar penumpukan karena kemalasan terselubung yang menyebabkan masalah seperti itu. Dalam hal ini, masalahnya adalah yang sumdiimplementasikan dalam hal foldl, yang memang menggunakan panggilan ekor, tetapi karena tidak mengevaluasi akumulator hanya semata-mata menghasilkan setumpuk thunks sebesar daftar asli. Masalahnya menghilang ketika beralih ke foldl' (+), yang mengevaluasi secara ketat dan dengan demikian mengembalikan WHN dalam panggilan ekornya. Atau, seperti yang saya katakan, jika Anda mengaktifkan optimisasi GHC!
Berhenti menghidupkan counterclockwis
aah - menarik, jadi jika tidak ada yang menunggu thunk (yaitu meninggalkan cetakan), pengumpul sampah akan mengambilnya (dari depan ke belakang)?
blabla999
1
BTW, tidak satu pun dari ini yang benar-benar ditentukan oleh standar Haskell: hanya diperlukan bahwa evaluasi tidak ketat , yaitu perhitungan nonterminating tidak akan memblokir selamanya jika hasilnya tidak sepenuhnya diperlukan. Berapa lama itu benar-benar memblokir hingga implementasi, dalam GHC malas standar tidak memblokir sama sekali sampai Anda meminta hasilnya.
Berhenti menghidupkan counterclockwis
2
haskell itu keren.
blabla999
12

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:

downTheRabbitHole
    |name deeperName nextLevel|

    nextLevel := self * 2.
    name := thisContext selector.
    deeperName := (name , '_') asSymbol.
    Class withoutUpdatingChangesDo:[
        nextLevel class 
            compile:deeperName , (thisContext method source copyFrom:name size+1).
    ].
    Transcript show:self; showCR:' - and down the rabbit hole...'.
    "/ self halt. "/ enable for debugging
    nextLevel perform:deeperName.

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):

{SmallInteger . LargeInteger } do:[:eachInfectedClass |
    (eachInfectedClass methodDictionary keys 
        select:[:nm| nm startsWith:'downTheRabbitHole_'])
            do:[:each| eachInfectedClass removeSelector:each]

atau menghabiskan waktu di browser, menghapus wonderland alice.

Berikut ini beberapa dari kepala jejak:

2 - and down the rabbit hole...
4 - and down the rabbit hole...
8 - and down the rabbit hole...
16 - and down the rabbit hole...
[...]
576460752303423488 - and down the rabbit hole...
1152921504606846976 - and down the rabbit hole...
2305843009213693952 - and down the rabbit hole...
[...]
1267650600228229401496703205376 - and down the rabbit hole...
2535301200456458802993406410752 - and down the rabbit hole...
5070602400912917605986812821504 - and down the rabbit hole...
[...]
162259276829213363391578010288128 - and down the rabbit hole...
324518553658426726783156020576256 - and down the rabbit hole...
[...]
and so on...

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.

blabla999
sumber
2
LOL +1 untuk ilmu hitam itu dalam bentuk murni
masterX244
Jika saya menemukan waktu, saya dapat "meningkatkan" dengan menggunakan metode anonim dari kelas anonim, untuk membuat lubang kelinci paling gelap yang pernah ...
blabla999
12

C #

Sangat besar struct, tanpa rekursi, C # murni, bukan kode tidak aman.

public struct Wyern
{
    double a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
public struct Godzilla
{
    Wyern a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
public struct Cyclops
{
    Godzilla a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
public struct Titan
{
    Cyclops a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
class Program
{
    static void Main(string[] args)
    {
        // An unhandled exception of type 'System.StackOverflowException' occurred in ConsoleApplication1.exe
        var A=new Titan();
        // 26×26×26×26×8 = 3655808 bytes            
        Console.WriteLine("Size={0}", Marshal.SizeOf(A));
    }
}

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)

public struct Wyern<T>
    where T: struct
{
    T a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;        
}


class Program
{
    static void Main(string[] args)
    {
        // An unhandled exception of type 'System.StackOverflowException' occurred in ConsoleApplication1.exe
        var A=new Wyern<Wyern<Wyern<Wyern<int>>>>();
    }
}
Ja72
sumber
Perlu lebih banyak lagi Kode kode generik: P
NPSF3000
Itu akan terlihat seperti rekursi, tetapi dimungkinkan dengan argumen tipe bersarang.
ja72
1
Tidak melihat jawaban C # struct Anda sebelum saya mengirimkan milik saya. Saya masih memiliki pendekatan yang sedikit berbeda, jadi mungkin kita membiarkan mereka hidup berdampingan.
Thomas Weller
11

C #

Kesalahan implementasi ==operator utama:

public class MyClass
{
    public int A { get; set; }

    public static bool operator ==(MyClass obj1, MyClass obj2)
    {
        if (obj1 == null)
        {
            return obj2 == null;
        }
        else
        {
            return obj1.Equals(obj2);
        }
    }

    public static bool operator !=(MyClass obj1, MyClass obj2)
    {
        return !(obj1 == obj2);
    }

    public override bool Equals(object obj)
    {
        MyClass other = obj as MyClass;
        if (other == null)
        {
            return false;
        }
        else
        {
            return A == other.A;
        }
    }
}

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.

Sebastian Negraszus
sumber
11

Mulai balas menggunakan SnakeYAML

class A
{

    public static void main(String[] a)
    {
         new org.yaml.snakeyaml.Yaml().dump(new java.awt.Point());
    }
}

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 Pointkode sumber)

Sunting: memberi tahu cara kerjanya:

SnakeYAML mencari sepasang getXXXdan setXXXmthod dengan nama yang sama untuk XXXdan mengembalikan tipe pengambil sama dengan parameter setter; dan yang mengejutkan, Pointkelas memiliki Point getLocation()dan void 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 dalam HashMapdan bertanya pada stackoverflow.com di atasnya.

masterX244
sumber
10

C #

pengambil properti yang diimplementasikan dengan salah

class C
{
   public int P { get { return P; } }
}

static void Main()
{
   int p = new C().P;
}
Alberto
sumber
14
MENURUT OPINI SAYA. Ini adalah contoh klasik untuk rekursi yang jelas ... (dan karenanya tidak valid)
Ole Albers
2
Yah, itu hanya jelas sekali Anda sudah melakukannya sekali dan tahu bahwa C # getter tidak bekerja seperti yang Anda kira pernah terjadi. Bagaimanapun, kode ini adalah deklarasi variabel anggota, jadi mengapa tidak membuat variabel anggota aktual?
meustrus
2
Ini tidak lebih dari cara berbelit-belitstatic void Main() { Main(); }
Jodrell
5
@Jodrell Anda tidak akan menulis rekursif secara Main()tidak sengaja. Tetapi cukup sederhana untuk menulis properti rekursif secara tidak sengaja dan kemudian dikacaukan oleh stack overflow.
svick
1
Ini akan berguna bagi seseorang yang mengambil C #.
2rs2ts