什么是导致堆栈溢出的最短代码?

Chr*_*ung 160 language-agnostic code-golf

为了纪念Stack Overflow的公开发布,导致堆栈溢出的最短代码是什么?任何语言欢迎.

ETA:只是要明确这个问题,因为我偶尔会看到一个Scheme用户:尾调用"递归"实际上是迭代,任何可以通过合适的编译器相对简单地转换为迭代解决方案的解决方案都不会算一算 :-P

ETA2:我现在选择了"最佳答案"; 看这篇文章的理由.感谢所有贡献的人!:-)

jru*_*lph 291

阅读这一行,并做两次说.


Pat*_*ick 212

所有这些答案都没有Befunge?我打赌相当多,这是他们所有人的最短解决方案:

1
Run Code Online (Sandbox Code Playgroud)

不开玩笑.亲自尝试:http://www.quirkster.com/iano/js/befunge.html

编辑:我想我需要解释一下.1操作数将1推入Befunge的内部堆栈,缺少任何其他内容将其置于语言规则下的循环中.

使用提供的解释,你会最终-我的意思是最终 --hit一个地步Javascript数组,表示Befunge堆栈变得过大的浏览器重新分配.如果你有一个简单的Befunge解释器,它有一个较小的有限堆栈 - 就像下面大多数语言一样 - 这个程序会更快地引起更明显的溢出.

  • 这是一个溢出速度更快的Befunge程序:```它每两次加载79个数字32,而不是数字1的2个副本. (28认同)
  • 你......我的浏览器崩溃了......把我的CPU风扇送到了过载状态. (18认同)
  • 嗯......但这真的是堆栈溢出还是只是无限循环?我的JS翻译确实*没有溢出,它只是休假,可以这么说. (8认同)
  • 它不是一个无限循环,因为1指令将1推入堆栈.最终,你的Befunge解释器将耗尽堆栈空间,但这需要一段时间.:) (3认同)
  • 惊人!我的计算机或浏览器(Opera)没有崩溃,但两个处理器都在100%运行,风扇速度为3. (2认同)

Gat*_*ler 174

你也可以在C#.net中试试这个

throw new StackOverflowException();
Run Code Online (Sandbox Code Playgroud)

  • 我的学究者说它不会导致任何堆栈溢出,只会引发异常.这就像是说最快被鲨鱼袭击的方法是站在海里尖叫"鲨鱼袭击!".尽管如此,我还是会投票.:) (29认同)
  • 如果堆栈在树林里溢出而周围没有人抓住,它是否会引发异常? (18认同)

Cod*_*ous 159

Nemerle:

会使编译器崩溃并发生StackOverflow异常:

def o(){[o()]}
Run Code Online (Sandbox Code Playgroud)


Chr*_*ung 119

我目前最好的(在x86组装中)是:

push eax
jmp short $-1
Run Code Online (Sandbox Code Playgroud)

这导致3个字节的目标代码(50 EB FD).对于16位代码,这也是可能的:

call $
Run Code Online (Sandbox Code Playgroud)

这也导致3个字节(E8 FD FF).

  • 问题是"[...]什么是导致堆栈溢出的最短代码?" 它没有指定源代码,解释代码,机器代码,目标代码或托管代码...... (37认同)
  • @lbrandy:有足够的人可以直接编写目标代码.我无法为x86做到这一点,但对于某个微处理器我能做到.我算这样的代码. (7认同)
  • 在"编译"(或组装)之后计算字节不是代码高尔夫. (6认同)

Ada*_*vis 113

PIC18

TK给出PIC18答案产生以下指令(二进制):

overflow
   PUSH
   0000 0000 0000 0101
   CALL overflow
   1110 1100 0000 0000
   0000 0000 0000 0000
Run Code Online (Sandbox Code Playgroud)

但是,仅CALL将执行堆栈溢出:

CALL $
1110 1100 0000 0000
0000 0000 0000 0000
Run Code Online (Sandbox Code Playgroud)

更小,更快的PIC18

但RCALL(相对调用)仍然较小(不是全局内存,所以不需要额外的2个字节):

RCALL $
1101 1000 0000 0000
Run Code Online (Sandbox Code Playgroud)

因此PIC18上最小的是单指令,16位(两个字节).这将在每个循环中花费2个指令周期.每个指令周期4个时钟周期,您有8个时钟周期.PIC18具有31级堆栈,因此在第32次循环之后,它将在256个时钟周期内溢出堆栈.在64MHz时,您将以4微秒和2个字节溢出堆栈.

PIC16F5x(更小更快)

但是,PIC16F5x系列使用12位指令:

CALL $
1001 0000 0000
Run Code Online (Sandbox Code Playgroud)

同样,每个循环两个指令周期,每个指令4个时钟,每个循环8个时钟周期.

但是,PIC16F5x具有两级堆栈,因此在第三个循环中它会溢出,在24条指令中.在20MHz时,它会在1.2微秒和1.5个字节内溢出.

英特尔4004

英特尔4004有一个8位CALL指令:

CALL $
0101 0000
Run Code Online (Sandbox Code Playgroud)

对于与ascii'P'相对应的好奇心.使用3级堆栈,需要24个时钟周期,总共32.4微秒和一个字节.(除非你超频你的4004 - 来吧,你知道你想要.)

这与befunge答案一样小,但比当前解释器中运行的befunge代码要快得多.


aku*_*aku 77

C#:

public int Foo { get { return Foo; } }
Run Code Online (Sandbox Code Playgroud)


Jul*_*iet 57

Hoot溢出!

//              v___v
let rec f o = f(o);(o)
//             ['---']
//             -"---"-
Run Code Online (Sandbox Code Playgroud)


Kon*_*lph 55

每项任务都需要合适的工具.符合SO溢出语言,经过优化可产生堆栈溢出:

so
Run Code Online (Sandbox Code Playgroud)

  • 如果您使用最少的代码生成溢出的专用语言,显然您会希望(1)空输入生成堆栈溢出代码(可能是运行从汇编代码条目生成的本机代码的小二进制文件)或(2) )所有输入程序产生所述二进制. (7认同)

Ale*_*x M 42

TeX的:

\def~{~.}~
Run Code Online (Sandbox Code Playgroud)

结果是:

! TeX capacity exceeded, sorry [input stack size=5000].
~->~
    .
~->~
    .
~->~
    .
~->~
    .
~->~
    .
~->~
    .
...
<*> \def~{~.}~

胶乳:

\end\end
Run Code Online (Sandbox Code Playgroud)

结果是:

! TeX capacity exceeded, sorry [input stack size=5000].
\end #1->\csname end#1
                      \endcsname \@checkend {#1}\expandafter \endgroup \if@e...
<*> \end\end


Den*_*sie 35

Z-80汇编程序 - 在内存位置0x0000:

rst 00
Run Code Online (Sandbox Code Playgroud)

一个字节 - 0xC7 - 将当前PC推送到堆栈并跳转到地址0x0000的无限循环.

  • 我记得一个空白的eprom将是所有0xff,这是第一个7(=调用0x0038)指令.这对于使用示波器调试硬件非常有用.当堆栈重复溢出时,地址总线将循环通过64K空间,并从0x0038中读取0xff的读取. (2认同)

Vin*_*vic 29

用英语讲:

recursion = n. See recursion.
Run Code Online (Sandbox Code Playgroud)

  • 克里斯,明智的人类大脑现在变得罕见. (73认同)
  • 任何明智的人类大脑都会尾巴调用优化对这个的解释,而不是爆炸.:-P (32认同)
  • 稀有......你的意思是他们存在? (20认同)
  • 谷歌递归 (11认同)

Kem*_*mal 29

另一个PHP示例:

<?
require(__FILE__);
Run Code Online (Sandbox Code Playgroud)

  • 甚至可以通过跳过括号来缩短(但包括空格代替第一个). (4认同)

stu*_*ith 26

BASIC中的以下内容如何:

10 GOSUB 10
Run Code Online (Sandbox Code Playgroud)

(我没有BASIC翻译,我担心这是猜测).

  • 这是一个"GOSUB",而不是"GOTO".因为它``RETURN'到它被调用的地方,当然它正在使用堆栈? (21认同)
  • 我在yabasic中运行这个只是为了它的乐趣,它几乎取下了我的电脑.感谢上帝malloc最终失败了,但我的分页就像没有明天一样. (6认同)
  • 由于BASIC是一种无堆栈语言,所以并不是堆栈溢出.即使VB(它有一个堆栈)也不会溢出,因为它只是跳跃而不是创建堆栈帧. (3认同)
  • 是的,我同意.我在80年代的BASIC中有很多*堆栈溢出. (3认同)
  • 哎呀抱歉Adam ...让我想起了当有人意外地编写一个递归分叉的程序时,在uni上的时间:取下整个Silicon Graphics服务器. (2认同)

Chr*_*ung 26

我喜欢Cody的答案堆,所以这是我在C++中的类似贡献:

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

typedef Overflow<0>::type Kaboom;
Run Code Online (Sandbox Code Playgroud)

无论如何都不是代码高尔夫球场,但是,元堆栈的任何东西都会溢出!:-P


Chr*_*ung 21

这是我的C贡献,重量为18个字符:

void o(){o();o();}
Run Code Online (Sandbox Code Playgroud)

这是一个很多难以尾调用优化!:-P

  • 不为我编译:"对'main'的未定义引用":P (4认同)
  • @Dinah:我的竞赛的一个限制因素是尾部调用优化并不算作递归; 它只是一个迭代循环.如果你只写了一次o(),可以将尾调用优化成这样的东西(由一个称职的编译器):"o:jmp o".通过2次调用o,编译器必须使用类似:"o:call o; jmp o".这是递归"调用"指令,使堆栈溢出. (3认同)

Jud*_*red 19

使用名为"s.bat"的Window批处理文件:

call s
Run Code Online (Sandbox Code Playgroud)


Tra*_*son 17

使用Javascript

为了削减更多的角色,并让自己从更多的软件商店中被踢出来,让我们一起来:

eval(i='eval(i)');
Run Code Online (Sandbox Code Playgroud)


Chr*_*oot 15

Groovy的:

main()
Run Code Online (Sandbox Code Playgroud)

$ groovy stack.groovy:

Caught: java.lang.StackOverflowError
    at stack.main(stack.groovy)
    at stack.run(stack.groovy:1)
 ...
Run Code Online (Sandbox Code Playgroud)


Gre*_*reg 15

请告诉我" GNU " 的缩写.

  • 或Eine(Eine不是Emacs),或Zwei(Zwei最初是Eine).:-P (4认同)

Rya*_*Fox 14

Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky);
Run Code Online (Sandbox Code Playgroud)

这里希望没有尾递归!

  • 这不是一个空指针异常吗?对不起,我知道这是个玩笑. (8认同)

bk1*_*k1e 12

C - 它不是最短的,但它是无递归的.它也不可移植:它在Solaris上崩溃,但是一些alloca()实现可能在这里返回错误(或调用malloc()).对printf()的调用是必要的.

#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;
}
Run Code Online (Sandbox Code Playgroud)


Cod*_*ous 11

Python:

so=lambda:so();so()
Run Code Online (Sandbox Code Playgroud)

或者:

def so():so()
so()
Run Code Online (Sandbox Code Playgroud)

如果Python优化尾调用...:

o=lambda:map(o,o());o()
Run Code Online (Sandbox Code Playgroud)


ask*_*sol 11

perl in 12 chars:

$_=sub{&$_};&$_
Run Code Online (Sandbox Code Playgroud)

bash in 10 chars(函数中的空格很重要):

i(){ i;};i
Run Code Online (Sandbox Code Playgroud)


use*_*456 11

尝试在一个汉堡上放4个以上的肉饼.堆栈溢出.


Chr*_*ung 10

我在这篇文章后选择了"最佳答案".但首先,我要感谢一些非常原始的贡献:

  1. aku的.每一个都探索了一种导致堆栈溢出的新的原始方法.做f(x)⇒f(f(x))的想法是我将在下一个条目中探讨的.:-)
  2. Cody是给Nemerle 编译器堆栈溢出的一个.
  3. 而且(有点勉强),GateKiller是一个关于抛出堆栈溢出异常的人.:-P

就像我喜欢上述情况一样,挑战在于打高尔夫球,对于受访者来说,我必须对最短的代码(Befunge入门)给予"最佳答案"; 我不相信任何人都能击败它(虽然康拉德当然已经尝试过),所以恭喜帕特里克!

看到大量的堆栈溢出递归解决方案,我很惊讶没有人(截至当前的写作)提出Y组合器(参见Dick Gabriel的文章,为什么Y,作为入门).我有一个使用Y组合器的递归解决方案,以及aku的f(f(x))方法.:-)

((Y (lambda (f) (lambda (x) (f (f x))))) #f)
Run Code Online (Sandbox Code Playgroud)


Ada*_*eld 8

这是Scheme中另一个有趣的:

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


Mis*_*sha 7

Java的

Java解决方案的版本略微缩短.

class X{public static void main(String[]a){main(a);}}
Run Code Online (Sandbox Code Playgroud)

  • 或(相同数量的字符):public static void main(String ... a){main();} (5认同)

And*_*vig 5

3个字节:

label:
  pusha
  jmp label

label:
  call label