Apa kode terpendek yang menyebabkan stack overflow? [Tutup]

160

Untuk memperingati peluncuran publik Stack Overflow, apa kode terpendek yang menyebabkan stack overflow? Selamat datang dalam bahasa apa pun.

ETA: Hanya untuk memperjelas pertanyaan ini, mengingat saya pengguna Skema sesekali: "rekursi" panggilan ekor benar-benar iterasi, dan solusi apa pun yang dapat dikonversi ke solusi berulang relatif sepele oleh kompiler yang layak tidak akan Dihitung. :-P

ETA2: Saya sekarang telah memilih "jawaban terbaik"; lihat posting ini untuk alasan. Terima kasih untuk semua orang yang berkontribusi! :-)

Chris Jester-Young
sumber

Jawaban:

212

Semua jawaban ini dan tidak ada Befunge? Saya akan bertaruh dalam jumlah yang adil itu solusi terpendek dari semuanya:

1

Tidak bercanda. Coba sendiri: http://www.quirkster.com/iano/js/befunge.html

EDIT: Saya kira saya perlu menjelaskan ini. 1 operan mendorong 1 ke tumpukan internal Befunge dan kurangnya hal lain menempatkannya dalam satu lingkaran di bawah aturan bahasa.

Menggunakan penerjemah yang disediakan, Anda pada akhirnya - dan maksud saya akhirnya - memukul titik di mana array Javascript yang mewakili tumpukan Befunge menjadi terlalu besar bagi peramban untuk dialokasikan kembali. Jika Anda memiliki juru bahasa Befunge sederhana dengan tumpukan yang lebih kecil dan terbatas - seperti halnya dengan sebagian besar bahasa di bawah ini - program ini akan menyebabkan luapan yang lebih nyata lebih cepat.

Patrick
sumber
8
Hmm ... tapi apakah ini benar-benar stack overflow atau hanya infinite loop? Penerjemah JS saya tidak meluap, hanya pergi berlibur, sehingga untuk berbicara.
Konrad Rudolph
3
Ini bukan loop tak terbatas, karena instruksi 1 mendorong 1 ke stack. Akhirnya, juru bahasa Befunge Anda akan kehabisan ruang tumpukan, tetapi itu akan memakan waktu cukup lama. :)
Patrick
18
Anda .. crash browser saya dan .. mengirim kipas CPU saya ke overdrive.
Sam152
2
Luar biasa! Komputer atau browser saya (Opera) tidak macet tetapi kedua prosesor berjalan pada 100% dan kecepatan kipas berada pada 3.
Secko
28
Berikut adalah program Befunge yang meluap lebih cepat: " Ini memuat 79 salinan dari nomor 32 setiap dua kali ia membungkus, daripada 2 salinan dari nomor 1.
KirarinSnow
291

Baca baris ini, dan lakukan apa yang dikatakannya dua kali .

jrudolph
sumber
174

Anda juga dapat mencoba ini di C # .net

throw new StackOverflowException();
GateKiller
sumber
29
Pedant dalam diriku mengatakan itu tidak menyebabkan tumpukan meluap, hanya melempar pengecualian. Itu seperti mengatakan cara tercepat untuk diserang oleh hiu adalah berdiri di laut dan berteriak "Serangan hiu!". Meskipun demikian, saya akan memilihnya. :)
Bernard
Nah - apakah ada perbedaan? Bisakah Anda menangkapnya dan melanjutkan? Atau apakah itu persis seperti stackoverflow di c #? Dalam hal ini, entah bagaimana itu adalah stackoverflow, karena tidak dapat dibedakan dari satu ... Namun - pilih-pilih untuk semua alasan di atas
Mo.
18
Jika tumpukan meluap di hutan tanpa ada yang menangkap, apakah itu membuang pengecualian?
Saya tidak akan mengatakan 'terpendek' karena tidak seperti Anda dapat mengkompilasi satu-liner seperti itu. Ini tidak membuang stack overflow cepat meskipun saya kira.
Dominic K
159

Nemerle :

Ini membuat crash kompiler dengan StackOverflowException:

def o(){[o()]}
Cody Brocious
sumber
119

Terbaik saya saat ini (dalam perakitan x86) adalah:

push eax
jmp short $-1

yang menghasilkan 3 byte kode objek ( 50 EB FD). Untuk kode 16-bit, ini juga memungkinkan:

call $

yang juga menghasilkan 3 byte ( E8 FD FF).

Chris Jester-Young
sumber
6
Menghitung byte setelah "kompilasi" (atau merakit) bukan kode-golf.
Louis Brandy
37
Pertanyaannya mengatakan "[...] apa kode terpendek yang menyebabkan stack overflow?" Itu tidak menentukan kode sumber, kode yang ditafsirkan, kode mesin, kode objek atau kode yang dikelola ...
Anders Sandvig
Sebagai catatan, server golf Shin memungkinkan Anda untuk mengirim kode objek untuk dinilai, meskipun itu akan menghitung semua header ELF Anda juga. Hmm ....
Chris Jester-Young
Lihat, misalnya, golf.shinh.org/p.rb?FizzBuzz#x86 untuk beberapa contohnya. (Jujur saya tidak tahu bagaimana orang bisa membuat biner ELF 99-byte, meskipun.) :-P
Chris Jester-Young
7
@ lbrandy: Ada cukup banyak orang yang dapat menulis kode objek secara langsung. Saya tidak bisa melakukannya untuk x86 tetapi untuk mikroprosesor tertentu saya bisa. Saya akan menghitung kode tersebut.
Joey
113

PIC18

The jawaban PIC18 diberikan oleh TK hasil dalam petunjuk berikut (biner):

overflow
   PUSH
   0000 0000 0000 0101
   CALL overflow
   1110 1100 0000 0000
   0000 0000 0000 0000

Namun, CALL saja akan melakukan stack overflow:

CALL $
1110 1100 0000 0000
0000 0000 0000 0000

PIC18 lebih kecil, lebih cepat

Tetapi RCALL (panggilan relatif) masih lebih kecil (bukan memori global, jadi tidak perlu tambahan 2 byte):

RCALL $
1101 1000 0000 0000

Jadi yang terkecil pada PIC18 adalah instruksi tunggal, 16 bit (dua byte). Ini akan membutuhkan 2 siklus instruksi per loop. Pada 4 siklus clock per siklus instruksi Anda punya 8 siklus clock. PIC18 memiliki tumpukan level 31, jadi setelah loop ke-32 ia akan meluap tumpukan, dalam 256 siklus clock. Pada 64MHz, Anda akan meluap tumpukan dalam 4 detik mikro dan 2 byte .

PIC16F5x (bahkan lebih kecil dan lebih cepat)

Namun, seri PIC16F5x menggunakan instruksi 12 bit:

CALL $
1001 0000 0000

Sekali lagi, dua siklus instruksi per loop, 4 jam per instruksi jadi 8 siklus clock per loop.

Namun, PIC16F5x memiliki tumpukan dua level, sehingga pada loop ketiga akan meluap, dalam 24 instruksi. Pada 20MHz, itu akan meluap dalam 1,2 detik mikro dan 1,5 byte .

Intel 4004

The Intel 4004 memiliki 8 bit panggilan subroutine instruksi:

CALL $
0101 0000

Untuk penasaran yang sesuai dengan ascii 'P'. Dengan tumpukan 3 level yang membutuhkan 24 siklus clock untuk total 32,4 detik mikro dan satu byte . (Kecuali jika Anda overclock 4004 Anda - ayolah, Anda tahu Anda ingin.)

Yang sekecil jawaban befunge, tapi jauh lebih cepat daripada kode befunge yang berjalan pada interpreter saat ini.

Adam Davis
sumber
77

C #:

public int Foo { get { return Foo; } }
aku
sumber
57

Hoot overflow!

//              v___v
let rec f o = f(o);(o)
//             ['---']
//             -"---"-
Juliet
sumber
55

Setiap tugas membutuhkan alat yang tepat. Memenuhi bahasa SO Overflow , dioptimalkan untuk menghasilkan stack overflow:

so
Konrad Rudolph
sumber
7
Jika Anda membuat bahasa khusus untuk menghasilkan luapan dengan kode minimal, jelas Anda ingin (1) input kosong menghasilkan stack overflow kode (mungkin biner kecil yang menjalankan kode asli yang dihasilkan dari entri kode assembly) atau (2) ) semua program input menghasilkan kata biner.
Jared Updike
Hmmm, tidak Turing lengkap. Saya tidak tahu apakah Anda bisa menyebutnya bahasa dulu ...
Adam Davis
42

TeX:

\def~{~.}~

Hasil dalam:

! Kapasitas TeX terlampaui, maaf [ukuran tumpukan input = 5000].
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
...
<*> \ def ~ {~.} ~

Getah:

\end\end

Hasil dalam:

! Kapasitas TeX terlampaui, maaf [ukuran tumpukan input = 5000].
\ end # 1 -> \ csname end # 1
                      \ endcsname \ @checkend {# 1} \ expandafter \ endgroup \ if @ e ...
<*> \ end \ end
Pi.
sumber
Karena ~aktif, dapat digunakan di tempat \a. Dan saya menemukan kode LaTeX secara tidak sengaja. :)
Josh Lee
35

Assembler Z-80 - di lokasi memori 0x0000:

rst 00

satu byte - 0xC7 - loop tanpa akhir untuk mendorong PC saat ini ke stack dan melompat ke alamat 0x0000.

Dennis Munsie
sumber
2
Saya ingat eprom kosong adalah semua 0xffs yang merupakan instruksi pertama 7 (= panggilan 0x0038). Itu akan berguna untuk men-debug perangkat keras Anda dengan osiloskop. Bus alamat akan berputar melalui ruang 64K sebagai tumpukan meluap berulang kali, diselingi dengan bacaan 0xff dari 0x0038.
Bill Forster
29

Dalam Bahasa Inggris:

recursion = n. See recursion.
Vinko Vrsalovic
sumber
32
Otak manusia mana pun yang masuk akal akan mengusahakan optimalisasi interpretasi yang satu ini juga, dan tidak meledak. :-P
Chris Jester-Young
73
Chris, otak manusia yang bijaksana menjadi langka belakangan ini.
Jason Z
20
kelangkaan ... maksudmu mereka ada?
Adam Lerman
11
Google rekursi
CodeFusionMobile
29

Contoh PHP lain:

<?
require(__FILE__);
disq
sumber
4
Anda bahkan dapat disingkat dengan melewatkan tanda kurung (tetapi termasuk ruang di tempat yang pertama).
alex
26

Bagaimana dengan yang berikut di BASIC:

10 GOSUB 10

(Saya tidak punya penerjemah DASAR yang saya takutkan jadi itu dugaan).

tukang kayu
sumber
3
Bukan stack overflow karena BASIC adalah bahasa stackless. Bahkan VB (yang memang memiliki tumpukan) tidak akan meluap karena ini hanya melompat, tidak membuat bingkai tumpukan.
Daniel Spiewak
21
Itu GOSUB, bukan GOTO. Karena RETURNdari mana ia dipanggil, pasti itu menggunakan tumpukan?
Tom
3
Ya saya setuju. Saya punya banyak tumpukan overflow di BASIC di tahun 80-an.
nickd
6
Saya menjalankan ini di yabasic hanya untuk bersenang-senang, dan hampir merobohkan komputer saya. Terima kasih Tuhan malloc akhirnya gagal, tapi saya paging tidak seperti hari esok.
Adam Rosenfield
2
Ups maaf Adam ... mengingatkan saya pada waktu di uni ketika seseorang tanpa sengaja menulis sebuah program yang secara forked bercabang: menurunkan seluruh server Silicon Graphics.
stusmith
26

Saya menyukai tumpukan jawaban Cody, jadi inilah kontribusi saya yang serupa, di C ++:

template <int i>
class Overflow {
    typedef typename Overflow<i + 1>::type type;
};

typedef Overflow<0>::type Kaboom;

Bukan entri kode golf dengan cara apa pun, tapi tetap saja, apa pun untuk tumpukan meta yang melimpah! :-P

Chris Jester-Young
sumber
21

Inilah kontribusi C saya, dengan bobot 18 karakter:

void o(){o();o();}

Ini jauh lebih sulit untuk mengoptimalkan panggilan! :-P

Chris Jester-Young
sumber
4
Tidak mengkompilasi untuk saya: "referensi tidak terdefinisi ke` utama '": P
Andrew Johnson
1
Saya tidak mengerti: mengapa memanggil o () 2x?
Dinah
3
@Dinah: Salah satu kendala dari kontes saya adalah optimalisasi tail-call tidak dihitung sebagai rekursi; itu hanya loop berulang. Jika Anda hanya menulis o () satu kali, itu bisa di-tail-tail dioptimalkan menjadi sesuatu seperti ini (oleh kompiler yang kompeten): "o: jmp o". Dengan 2 panggilan o, kompiler harus menggunakan sesuatu seperti: "o: call o; jmp o". Ini adalah instruksi "panggilan" rekursif yang membuat stack overflow.
Chris Jester-Young
Anda benar - saya tidak memperhatikan bagian itu. Terimakasih atas klarifikasinya.
Dinah
19

Menggunakan file batch Window bernama "s.bat":

call s
Jude Allred
sumber
17

Javascript

Untuk memangkas beberapa karakter, dan untuk mengeluarkan diri dari lebih banyak toko perangkat lunak, mari kita ikuti:

eval(i='eval(i)');
Travis Wilson
sumber
15

Asyik:

main()

$ groovy stack.groovy:

Caught: java.lang.StackOverflowError
    at stack.main(stack.groovy)
    at stack.run(stack.groovy:1)
 ...
Chris Broadfoot
sumber
Terpilih karena cukup menarik. Mengekspos kelemahan yang agak menjengkelkan di kompiler Groovy (panggilan ekor tersebut dapat diuraikan pada waktu kompilasi).
Daniel Spiewak
Apakah Anda yakin itu panggilan ekor? bahwa jatuh dari akhir program tidak meminta shell juru bahasa?
Aaron
15

Tolong beritahu saya apa singkatan " GNU ".

Greg
sumber
4
Atau Eine (Eine bukan Emacs), atau Zwei (awalnya Zwei Eine). :-P
Chris Jester-Young
Atau YAML, atau WINE, atau XNA, atau yang lainnya di en.wikipedia.org/wiki/Recursive_acronym
TM.
Drei (Drei benar-benar Emacs Incognito), Fier (Fier adalah Emacs Reinvented) - ok jadi saya hanya mengarangnya :-)
Ferruccio
14
Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky);

Inilah harapan agar tidak ada rekursi ekor!

Ryan Fox
sumber
1
Hehe, lucu. Terkait dengan percakapan, gagasan tentang "efek ruang gema" juga cukup menarik. Tidak terlalu banyak menumpuk yang mendorong, tapi tetap saja.
Chris Jester-Young
8
Bukankah ini pengecualian null pointer? Maaf, saya tahu ini lelucon.
jamesh
12

C - Ini bukan yang terpendek, tetapi bebas rekursi. Ini juga tidak portabel: crash di Solaris, tetapi beberapa alokasi alokasi () mungkin mengembalikan kesalahan di sini (atau panggil malloc ()). Panggilan ke printf () diperlukan.

#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;
}
bk1e
sumber
Anda juga bisa melakukan "ulimit -s16" untuk mengatur stack menjadi sangat kecil. Ada yang lebih kecil dari sekitar 16 dan program ini bahkan tidak berjalan (tampaknya tidak cukup arg!).
Andrew Johnson
11

perl dalam 12 karakter:

$_=sub{&$_};&$_

bash dalam 10 karakter (ruang dalam fungsi itu penting):

i(){ i;};i
askol
sumber
11

Python :

so=lambda:so();so()

Kalau tidak:

def so():so()
so()

Dan jika Python dioptimalkan panggilan ekor ...:

o=lambda:map(o,o());o()
Cody Brocious
sumber
Beruntung bagi Anda, Python tidak melakukan optimasi tail-call; jika tidak, itu akan didiskualifikasi seperti dua jawaban lain sejauh ini. :-P
Chris Jester-Young
10

Saya memilih "jawaban terbaik" setelah posting ini. Tetapi pertama-tama, saya ingin mengakui beberapa kontribusi yang sangat orisinal:

  1. yang aku. Masing-masing mengeksplorasi cara baru dan asli yang menyebabkan stack overflow. Gagasan untuk melakukan f (x) ⇒ f (f (x)) adalah ide yang akan saya eksplorasi di entri saya berikutnya, di bawah ini. :-)
  2. Cody yang memberi Nemerle compiler stack overflow.
  3. Dan (sedikit enggan), salah satu GateKiller tentang melemparkan pengecualian stack overflow. :-P

Seperti halnya saya menyukai hal di atas, tantangannya adalah tentang melakukan golf kode, dan untuk bersikap adil kepada responden, saya harus memberikan "jawaban terbaik" untuk kode terpendek, yaitu entri Befunge; Saya tidak percaya ada orang yang bisa mengalahkan itu (walaupun Konrad sudah mencoba), jadi selamat Patrick!

Melihat sejumlah besar solusi stack-overflow-by-recursion, saya terkejut bahwa tidak ada yang (pada tulisan saat ini) mengangkat kombinator Y (lihat esai Dick Gabriel, The Why of Y , untuk primer). Saya punya solusi rekursif yang menggunakan kombinator Y, serta pendekatan aku (f (x)). :-)

((Y (lambda (f) (lambda (x) (f (f x))))) #f)
Chris Jester-Young
sumber
8

Berikut ini satu lagi yang menarik dari Skema:

((lambda (x) (xx)) (lambda (x) (xx)))
Adam Rosenfield
sumber
Sangat bagus, dan ada simetri yang bagus untuk itu juga. Juga, untuk menggunakan formulasi (lambda (x) (xx)): ((Y (lambda (x) (xx)))) #f) juga sangat menyenangkan!
Chris Jester-Young
Oh, cantik. Ia bekerja di Ruby juga, meskipun tidak secantik di Skema: lambda {| x | x.call x} .call lambda {| x | x.call x}
Wayne Conrad
7

Jawa

Versi solusi Java yang sedikit lebih pendek.

class X{public static void main(String[]a){main(a);}}
Misha
sumber
5
Atau (jumlah yang sama karakter): public static void main (String ... a) {main ();}
Michael Myers
Atau untuk orang-orang TDD (jumlah karakter yang sama): kelas publik ${@org.junit.Test public void $ () {$ ();}}
mhaller
Masih bukan yang terpendek (lihat jawaban saya)
Draemon
6
xor esp, esp
ret
a1k0n
sumber
itu tidak benar-benar stack overflow, tapi itu bagus: D
botismarius
5

3 byte:

label:
  pusha
  jmp label

Memperbarui

Menurut dokumentasi (lama?) Intel (?) , Ini juga 3 byte:

label:
  call label

Anders Sandvig
sumber
Ini 3 byte dalam mode 32-bit. Jawaban yang bagus, mengingat itu akan mengisi tumpukan lebih cepat daripada jawaban saya!
Chris Jester-Young
Menurut penguin.cz/~literakl/intel/j.html#JMP , jmp adalah 3 byte dengan alamat tujuan relatif 8, 16 atau 32 bit. Pusha juga 1 byte, yang membuat total 4
Anders Sandvig
Ada tiga jenis jmp, pendek, dekat, dan jauh. Jmp pendek (menggunakan opcode 0xEB) adalah dua byte. Tujuan harus antara -128 dan 127 byte dari instruksi selanjutnya. :-)
Chris Jester-Young
Mungkin kau benar. Saya terlalu malas untuk menggali assembler saya dan memverifikasi ...;)
Anders Sandvig