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

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.


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 .


174

Anda juga dapat mencoba ini di C # .net

throw new StackOverflowException();

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()]}

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


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.


77

C #:

public int Foo { get { return Foo; } }

57

Hoot overflow!

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

55

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

so

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

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.


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

Contoh PHP lain:

<?
require(__FILE__);

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


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


21

Inilah kontribusi C saya, dengan bobot 18 karakter:

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

Ini jauh lebih sulit untuk mengoptimalkan panggilan! :-P


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


17

Javascript

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

eval(i='eval(i)');

15

Asyik:

main()

$ groovy stack.groovy:

Caught: java.lang.StackOverflowError
    at stack.main(stack.groovy)
    at stack.run(stack.groovy:1)
 ...

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


14
Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky);

Inilah harapan agar tidak ada rekursi ekor!


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;
}

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

11

coba dan taruh lebih dari 4 roti di satu burger. stack overflow.


1
Di sini di Selandia Baru kami memiliki Burger Wisconsin, di mana mereka menggunakan roti yang besar tapi tipis. Saya yakin Anda dapat menumpuk lebih dari 4 jika ingin; itu akan menjadi burger yang sangat mahal!
Chris Jester-Young



11

Python :

so=lambda:so();so()

Kalau tidak:

def so():so()
so()

Dan jika Python dioptimalkan panggilan ekor ...:

o=lambda:map(o,o());o()

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)

8

Berikut ini satu lagi yang menarik dari Skema:

((lambda (x) (xx)) (lambda (x) (xx)))

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);}}

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


5

3 byte:

label:
  pusha
  jmp label

Memperbarui

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

label:
  call label


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
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.