Mã ngắn nhất để gây ra lỗi tràn ngăn xếp là gì? [đóng cửa]


160

Để kỷ niệm sự ra mắt công khai của Stack Overflow, đoạn mã ngắn nhất để gây ra lỗi tràn stack là gì? Bất kỳ ngôn ngữ chào mừng.

ETA: Chỉ cần rõ ràng về câu hỏi này, vì tôi là người dùng Scheme không thường xuyên: gọi "đệ quy" thực sự là lặp đi lặp lại, và bất kỳ giải pháp nào có thể được chuyển đổi thành một giải pháp lặp tương đối tầm thường bởi một trình biên dịch đàng hoàng sẽ không được tính. :-P

ETA2: Bây giờ tôi đã chọn một câu trả lời hay nhất của người Viking; xem bài này cho lý do. Cảm ơn những người đã đóng góp! :-)

Câu trả lời:


212

Tất cả những câu trả lời và không có Befunge? Tôi muốn đặt một số tiền hợp lý, đó là giải pháp ngắn nhất trong tất cả:

1

Không đùa. Hãy tự mình thử: http://www.quirkster.com/iano/js/befunge.html

EDIT: Tôi đoán tôi cần phải giải thích điều này. Toán hạng 1 đẩy 1 lên ngăn xếp bên trong của Befunge và việc thiếu bất cứ thứ gì khác sẽ đặt nó vào một vòng lặp theo quy tắc của ngôn ngữ.

Sử dụng trình thông dịch được cung cấp, cuối cùng bạn sẽ - và ý tôi là cuối cùng - đó là điểm mà mảng Javascript đại diện cho ngăn xếp Befunge trở nên quá lớn để trình duyệt phân bổ lại. Nếu bạn có một trình thông dịch Befunge đơn giản với ngăn xếp nhỏ hơn và giới hạn - như trường hợp của hầu hết các ngôn ngữ bên dưới - chương trình này sẽ gây ra lỗi tràn nhanh hơn đáng chú ý.


8
Hmm, nhưng đây thực sự là một ngăn xếp tràn hay chỉ là một vòng lặp vô hạn? Trình thông dịch JS của tôi không bị tràn, nó chỉ đi nghỉ, nên nói.
Konrad Rudolph

3
Đây không phải là một vòng lặp vô hạn, bởi vì lệnh 1 đẩy 1 lên ngăn xếp. Cuối cùng, trình thông dịch Befunge của bạn sẽ hết dung lượng ngăn xếp, nhưng sẽ mất một lúc. :)
Patrick

18
Bạn .. đã làm sập trình duyệt của tôi và .. đã gửi quạt CPU của tôi vào tình trạng quá tải.
Sam52

2
Kinh ngạc! Máy tính hoặc trình duyệt của tôi (Opera) không gặp sự cố nhưng cả hai bộ xử lý đều chạy 100% và tốc độ quạt là 3.
Secko

28
Đây là một chương trình Befunge tràn nhanh hơn: " Nó tải 79 bản sao của số 32 cứ sau hai lần, nó thay vì 2 bản sao của số 1.
KirarinSnow

291

Đọc dòng này, và làm những gì nó nói hai lần .


174

Bạn cũng có thể thử điều này trong C # .net

throw new StackOverflowException();

29
Người bán hàng trong tôi nói rằng nó không khiến cho bất kỳ ngăn xếp nào bị tràn, chỉ cần ném một ngoại lệ. Điều đó giống như nói cách nhanh nhất để bị cá mập tấn công là đứng dưới biển và hét lên "Cá mập tấn công!". Mặc dù vậy, tôi sẽ bỏ phiếu cho nó. :)
Bernard

Chà - có sự khác biệt? Bạn có thể bắt nó và tiếp tục? Hoặc nó chính xác giống như một stackoverflow trong c #? Trong trường hợp đó, bằng cách nào đó nó là một stackoverflow, vì nó không thể phân biệt được với một ... Tuy nhiên - upvote cho tất cả các lý do trên
Mo

18
Nếu một chồng chất tràn trong rừng mà không có ai xung quanh để bắt, liệu nó có ném ngoại lệ không?

Tôi sẽ không nói 'ngắn nhất' vì không giống như bạn có thể biên dịch một lớp lót như thế. Nó không ném một chồng tràn nhanh chóng mặc dù tôi đoán.
Đaminh K

159

Người da đen :

Điều này làm sập trình biên dịch với StackOverflowException:

def o(){[o()]}

119

Tốt nhất hiện tại của tôi (trong x86 lắp ráp) là:

push eax
jmp short $-1

dẫn đến 3 byte mã đối tượng ( 50 EB FD). Đối với mã 16 bit, điều này cũng có thể:

call $

mà cũng dẫn đến 3 byte ( E8 FD FF).


6
Đếm các byte sau khi "biên dịch" (hoặc lắp ráp) không phải là mã golf.
Louis Brandy

37
Câu hỏi cho biết "[...] mã nào ngắn nhất để gây ra lỗi tràn ngăn xếp?" Nó không chỉ định mã nguồn, mã thông dịch, mã máy, mã đối tượng hoặc mã được quản lý ...
Anders Sandvig

Đối với hồ sơ, máy chủ chơi gôn của Shin cho phép bạn gửi mã đối tượng để được đánh giá, mặc dù nó cũng sẽ tính tất cả các tiêu đề ELF của bạn. Hmm ....
Chris Jester-Young

Xem, ví dụ, golf.shinh.org/p.rb?FizzBuzz#x86 để biết một số ví dụ về điều này. (Thành thật mà nói tôi không biết làm thế nào mọi người có thể tạo các nhị phân ELF 99 byte.) :-P
Chris Jester-Young

7
@lbrandy: Có đủ người có thể viết mã đối tượng trực tiếp. Tôi không thể làm điều đó cho x86 nhưng đối với một bộ vi xử lý nhất định thì tôi có thể. Tôi sẽ đếm mã như vậy.
Joey

113

PIC18

Các câu trả lời PIC18 do TK kết quả trong các hướng dẫn sau đây (nhị phân):

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

Tuy nhiên, một mình CALL sẽ thực hiện tràn ngăn xếp:

CALL $
1110 1100 0000 0000
0000 0000 0000 0000

PIC18 nhỏ hơn, nhanh hơn

Nhưng RCALL (cuộc gọi tương đối) vẫn nhỏ hơn (không phải bộ nhớ chung, do đó không cần thêm 2 byte):

RCALL $
1101 1000 0000 0000

Vì vậy, nhỏ nhất trên PIC18 là một lệnh đơn, 16 bit (hai byte). Điều này sẽ mất 2 chu kỳ hướng dẫn trên mỗi vòng lặp. Ở 4 chu kỳ đồng hồ trên mỗi chu kỳ hướng dẫn, bạn có 8 chu kỳ đồng hồ. PIC18 có ngăn xếp 31 cấp, do đó, sau vòng thứ 32, nó sẽ tràn vào ngăn xếp, trong 256 chu kỳ đồng hồ. Ở 64 MHz, bạn sẽ tràn ngăn xếp trong 4 micro giây và 2 byte .

PIC16F5x (thậm chí nhỏ hơn và nhanh hơn)

Tuy nhiên, sê-ri PIC16F5x sử dụng các hướng dẫn 12 bit:

CALL $
1001 0000 0000

Một lần nữa, hai chu kỳ lệnh trên mỗi vòng lặp, 4 đồng hồ trên mỗi lệnh để 8 chu kỳ đồng hồ trên mỗi vòng lặp.

Tuy nhiên, PIC16F5x có một ngăn xếp hai cấp độ, vì vậy trên vòng lặp thứ ba, nó sẽ tràn ra, trong 24 hướng dẫn. Ở 20 MHz, nó sẽ tràn trong 1,2 micro giây và 1,5 byte .

Intel 4004

Các Intel 4004 có 8 bit lệnh gọi chương trình con:

CALL $
0101 0000

Đối với sự tò mò tương ứng với một ascii 'P'. Với ngăn xếp 3 cấp, mất 24 chu kỳ xung nhịp với tổng cộng 32,4 micro giây và một byte . (Trừ khi bạn ép xung 4004 của mình - thôi nào, bạn biết bạn muốn.)

Nó nhỏ như câu trả lời của befunge, nhưng nhanh hơn nhiều so với mã befunge đang chạy trong các trình thông dịch hiện tại.


77

C #:

public int Foo { get { return Foo; } }

57

Hoot tràn!

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

55

Mỗi nhiệm vụ cần công cụ phù hợp. Đáp ứng ngôn ngữ tràn SO , được tối ưu hóa để tạo ra tràn ngăn xếp:

so

7
Nếu bạn đang tạo một ngôn ngữ chuyên biệt để tạo ra các luồng tràn với tối thiểu mã, rõ ràng bạn sẽ muốn (1) đầu vào trống tạo ra mã tràn ngăn xếp (có thể là một nhị phân nhỏ chạy mã gốc được tạo từ mục nhập mã lắp ráp) hoặc (2 ) tất cả các chương trình đầu vào sản xuất nhị phân nói.
Jared Updike

Hmmm, không hoàn thành Turing. Tôi không biết liệu bạn có thể gọi nó là ngôn ngữ chưa ...
Adam Davis

42

TeX:

\def~{~.}~

Kết quả trong:

! Vượt quá dung lượng TeX, xin lỗi [kích thước ngăn xếp đầu vào = 5000].
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
...
<*> \ def ~ {~.} ~

Mủ cao su:

\end\end

Kết quả trong:

! Vượt quá dung lượng TeX, xin lỗi [kích thước ngăn xếp đầu vào = 5000].
\ end # 1 -> \ csname end # 1
                      \ endcsname \ @checkend {# 1} \ expandafter \ endgroup \ if @ e ...
<*> \ end \ end

~là hoạt động, nó có thể được sử dụng thay thế \a. Và tôi đã phát hiện ra mã LaTeX hoàn toàn tình cờ. :)
Josh Lee

35

Trình biên dịch Z-80 - tại vị trí bộ nhớ 0x0000:

rst 00

một byte - 0xC7 - vòng lặp vô tận đẩy PC hiện tại lên ngăn xếp và nhảy tới địa chỉ 0x0000.


2
Tôi nhớ một eprom trống sẽ là tất cả các 0xff là hướng dẫn đầu tiên 7 (= gọi 0x0038). Điều đó sẽ hữu ích cho việc gỡ lỗi phần cứng của bạn bằng máy hiện sóng. Bus địa chỉ sẽ quay vòng qua không gian 64K khi ngăn xếp tràn liên tục, xen kẽ với các lần đọc 0xff từ 0x0038.
Bill Forster

29

Bằng tiếng Anh:

recursion = n. See recursion.

32
Bất kỳ bộ não con người hợp lý nào cũng sẽ gọi đuôi để tối ưu hóa việc giải thích cái này, và không nổ tung. :-P
Chris Jester-Young

73
Chris, bộ não con người hợp lý đang trở nên hiếm hoi những ngày này.
Jason Z

20
hiếm có ... ý bạn là chúng tồn tại?
Adam Lerman

11
Google đệ quy
CodeFusionMobile

29

Một ví dụ PHP khác:

<?
require(__FILE__);

4
Bạn thậm chí có thể được rút ngắn bằng cách bỏ qua dấu ngoặc đơn (nhưng bao gồm khoảng trắng ở vị trí đầu tiên).
alex

26

Làm thế nào về những điều sau đây trong BASIC:

10 GOSUB 10

(Tôi không có trình thông dịch BASIC. Tôi sợ đó là một phỏng đoán).


3
Không thực sự là một ngăn xếp tràn vì BASIC là một ngôn ngữ không có chồng. Ngay cả VB (không có ngăn xếp) cũng sẽ không tràn vào điều này vì nó chỉ nhảy, không tạo khung stack.
Daniel Spiewak

21
Đó là một GOSUB, không phải a GOTO. Vì nó RETURNđược gọi đến từ đâu, chắc chắn nó đang sử dụng một ngăn xếp?
Tom

3
Vâng tôi đồng ý. Tôi đã có nhiều ngăn xếp tràn vào BASIC trong những năm 80.
nickd

6
Tôi chạy cái này trong yabasic chỉ vì niềm vui của nó, và nó gần như đã làm hỏng máy tính của tôi. Cảm ơn thần malloc cuối cùng đã thất bại, nhưng tôi đã phân trang như không có ngày mai.
Adam Rosenfield

2
Rất tiếc, Adam ... làm tôi nhớ đến một thời điểm tại uni khi ai đó vô tình viết một chương trình rẽ nhánh: đã đánh sập toàn bộ máy chủ Đồ họa Silicon.
stusmith

26

Tôi yêu hàng đống câu trả lời của Cody, vì vậy đây là đóng góp tương tự của tôi, trong C ++:

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

typedef Overflow<0>::type Kaboom;

Không phải là một mục nhập mã bằng bất kỳ phương tiện nào, nhưng vẫn, bất cứ điều gì cho một meta stack tràn! :-P


21

Đây là đóng góp C của tôi, nặng 18 ký tự:

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

Điều này là khó khăn hơn rất nhiều để tối ưu hóa cuộc gọi đuôi! :-P


4
Không biên dịch cho tôi: "tham chiếu không xác định cho` main '": P
Andrew Johnson

1
Tôi không hiểu: tại sao gọi o () 2x?
Dinah

3
@Dinah: Một trong những hạn chế của cuộc thi của tôi là tối ưu hóa cuộc gọi đuôi không được tính là đệ quy; nó chỉ là một vòng lặp. Nếu bạn chỉ viết o () một lần, đó có thể là cuộc gọi đuôi được tối ưu hóa thành một cái gì đó như thế này (bởi một trình biên dịch có thẩm quyền): "o: jmp o". Với 2 cuộc gọi của o, trình biên dịch phải sử dụng một cái gì đó như: "o: call o; jmp o". Đó là hướng dẫn "gọi" đệ quy làm cho ngăn xếp tràn.
Chris Jester-Young

Bạn đã đúng - tôi đã không chú ý đến phần đó. Cảm ơn bạn đã làm rõ.
Dinah


17

Javascript

Để cắt giảm thêm một vài nhân vật và để khiến chúng ta bị loại khỏi nhiều cửa hàng phần mềm hơn, hãy cùng:

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

15

Groovy:

main()

$ Groovy stack.groovy:

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

Bình chọn vì nó khá thú vị. Mặc dù có một điểm yếu khá khó chịu trong trình biên dịch Groovy (các lệnh gọi đuôi như vậy có thể được nội tuyến tại thời gian biên dịch).
Daniel Spiewak

bạn có chắc đó là một cuộc gọi đuôi? rơi ra khỏi phần cuối của chương trình không gọi trình biên dịch?
Aaron

15

Vui lòng cho tôi biết từ viết tắt " GNU " là viết tắt của từ gì.


4
Hoặc Eine (Eine không phải là Emacs), hoặc Zwei (Zwei ban đầu là Eine). :-P
Chris Jester-Young

Hoặc YAML, hoặc RƯỢU, hoặc XNA, hoặc bất kỳ phần còn lại nào tại en.wikipedia.org/wiki/Recursive_acronym
TM.

Drei (Drei là Really Emacs Incognito), Fier (Fier là Emacs Sáng tạo lại) - ok vì vậy tôi chỉ cần thực hiện những lên :-)
Ferruccio

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

Đây là hy vọng không có đệ quy đuôi!


1
Hehe, buồn cười. Liên quan đến các cuộc hội thoại, ý tưởng về "hiệu ứng buồng vang" cũng khá thú vị. Không hoàn toàn chồng chất gây ra, nhưng vẫn còn.
Chris Jester-Young

8
Đây sẽ không phải là một ngoại lệ con trỏ null? Xin lỗi, tôi biết đó là một trò đùa.
jamesh

12

C - Nó không phải là ngắn nhất, nhưng nó không có đệ quy. Nó cũng không khả dụng: nó gặp sự cố với Solaris, nhưng một số triển khai alloca () có thể trả về lỗi ở đây (hoặc gọi malloc ()). Cuộc gọi đến printf () là cần thiết.

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

Bạn cũng có thể chỉ cần thực hiện "ulimit -s16" để đặt ngăn xếp thực sự nhỏ. Bất kỳ nhỏ hơn khoảng 16 và chương trình thậm chí không chạy (rõ ràng không đủ đối số!).
Andrew Johnson

11

perl trong 12 ký tự:

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

bash trong 10 ký tự (không gian trong hàm là quan trọng):

i(){ i;};i

11

thử và đặt hơn 4 patties vào một chiếc burger. chồng tràn.


1
Ở New Zealand, chúng tôi có Burger Wisconsin, nơi họ sử dụng những miếng thịt to nhưng mỏng. Tôi chắc chắn rằng bạn có thể xếp nhiều hơn 4 trong số đó nếu bạn muốn; Nó sẽ là một burger rất đắt tiền mặc dù!
Chris Jester-Young



11

Python :

so=lambda:so();so()

Cách khác:

def so():so()
so()

Và nếu Python tối ưu hóa các cuộc gọi đuôi ...:

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

May mắn cho bạn, Python không thực hiện tối ưu hóa cuộc gọi đuôi; nếu không, nó sẽ bị loại như hai câu trả lời khác cho đến nay. :-P
Chris Jester-Young

10

Tôi đang chọn câu trả lời hay nhất trên thế giới sau bài đăng này. Nhưng trước tiên, tôi muốn ghi nhận một số đóng góp rất nguyên bản:

  1. những người aku. Mỗi người khám phá một cách mới và nguyên bản gây ra tràn ngăn xếp. Ý tưởng thực hiện f (x) f (f (x)) là một ý tưởng tôi sẽ khám phá trong mục tiếp theo của tôi, bên dưới. :-)
  2. Một trong những Cody đã cung cấp cho trình biên dịch Nemerle một ngăn xếp chồng.
  3. Và (một chút miễn cưỡng), GateKiller nói về việc ném một ngoại lệ tràn ngăn xếp. :-P

Nhiều như tôi yêu thích ở trên, thử thách là về việc chơi golf mã, và để công bằng cho những người được hỏi, tôi phải trao giải cho câu trả lời hay nhất của ếch với mã ngắn nhất, đó là mục Befunge; Tôi không tin bất cứ ai sẽ có thể đánh bại điều đó (mặc dù Konrad chắc chắn đã cố gắng), vì vậy xin chúc mừng Patrick!

Nhìn thấy số lượng lớn các giải pháp đệ quy chồng lên nhau, tôi ngạc nhiên rằng không có ai (như cách viết hiện tại) đưa ra tổ hợp Y (xem bài tiểu luận của Dick Gabriel, The Why of Y , cho một đoạn mồi). Tôi có một giải pháp đệ quy sử dụng tổ hợp Y, cũng như phương pháp f (f (x)) của aku. :-)

((Y (lambda (f) (lambda (x) (f (f x))))) #f)

8

Đây là một điều thú vị khác từ Đề án:

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

Rất đẹp, và cũng có một sự đối xứng tốt với nó. Ngoài ra, để sử dụng công thức (lambda (x) (xx)): ((Y (lambda (x) (xx))) #f) cũng rất thú vị!
Chris Jester-Young

Ồ, thật đẹp. Nó cũng hoạt động trong Ruby, mặc dù không đẹp như trong Scheme: lambda {| x | x.call x} .call lambda {| x | x.call x}
Wayne Conrad

7

Java

Phiên bản ngắn hơn một chút của giải pháp Java.

class X{public static void main(String[]a){main(a);}}

5
Hoặc (cùng số lượng ký tự): public static void main (Chuỗi ... a) {main ();}
Michael Myers

Hoặc dành cho những người TDD (cùng số ký tự): lớp công khai $ nd@org.junit.Test public void $ () {$ ();}}
mhaller

Vẫn không phải là ngắn nhất (xem câu trả lời của tôi)
Draemon


5

3 byte:

label:
  pusha
  jmp label

Cập nhật

Theo tài liệu Intel (?) Cũ (?) , Đây cũng là 3 byte:

label:
  call label


Đó là 3 byte ở chế độ 32 bit. Câu trả lời hay, xem xét nó sẽ lấp đầy ngăn xếp nhanh hơn nhiều so với câu trả lời của tôi!
Chris Jester-Young

Theo penguin.cz/~literakl/intel/j.html#JMP , jmp là 3 byte với địa chỉ đích tương đối 8, 16 hoặc 32 bit. Pusha cũng là 1 byte, tạo ra tổng cộng 4
Anders Sandvig

Có ba loại jmp, ngắn, gần và xa. Jmp ngắn (sử dụng opcode 0xEB) là hai byte. Đích đến phải nằm trong khoảng từ -128 đến 127 byte so với lệnh tiếp theo. :-)
Chris Jester-Young

Có thể bạn đúng. Tôi quá lười để đào bới trình biên dịch chương trình của mình và xác minh ...;)
Anders Sandvig
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.