为了纪念Stack Overflow的公开发布,导致堆栈溢出的最短代码是什么? 任何语言欢迎。
ETA:只是要明确这个问题,因为我偶尔会看到一个Scheme用户:尾调用"递归"实际上是迭代,任何可以通过合适的编译器相对简单地转换为迭代解决方案的解决方案都不会 算一算:-P
ETA2:我现在选择了"最佳答案"; 看这篇文章的理由。 感谢所有贡献的人!:-)
阅读这一行,并做两次说。
所有这些答案都没有Befunge?我打赌相当多,这是他们所有人的最短解决方案:
不开玩笑。亲自尝试:http://www.quirkster.com/iano/js/befunge.html
编辑:我想我需要解释一下。 1操作数将1推入Befunge的内部堆栈,缺少任何其他内容将其置于语言规则下的循环中。
使用提供的解释器,你最终 - 我的意思是最终 - 达到了一个点,其中代表Befunge堆栈的Javascript数组变得太大而浏览器无法重新分配。如果你有一个简单的Befunge解释器,它有一个较小的有限堆栈 - 就像下面大多数语言一样 - 这个程序会更快地引起更明显的溢出。
你也可以在C#.net中试试这个
1
| throw new StackOverflowException(); |
Nemerle:
这会使编译器崩溃并发生StackOverflow异常:
我目前最好的(在x86组装中)是:
这导致3个字节的目标代码(50 EB FD)。对于16位代码,这也是可能的:
这也导致3个字节(E8 FD FF)。
PIC18
TK给出的PIC18答案产生以下指令(二进制):
1 2 3 4 5 6
| overflow
PUSH
0000 0000 0000 0101
CALL overflow
1110 1100 0000 0000
0000 0000 0000 0000 |
但是,仅CALL将执行堆栈溢出:
1 2 3
| CALL $
1110 1100 0000 0000
0000 0000 0000 0000 |
更小,更快的PIC18
但RCALL(相对调用)仍然较小(不是全局内存,所以不需要额外的2个字节):
1 2
| RCALL $
1101 1000 0000 0000 |
因此PIC18上最小的是单指令,16位(两个字节)。这将在每个循环中花费2个指令周期。每个指令周期4个时钟周期,您有8个时钟周期。 PIC18具有31级堆栈,因此在第32次循环之后,它将在256个时钟周期内溢出堆栈。在64MHz时,您将以4微秒和2个字节溢出堆栈。
PIC16F5x(更小更快)
但是,PIC16F5x系列使用12位指令:
同样,每个循环两个指令周期,每个指令4个时钟,每个循环8个时钟周期。
但是,PIC16F5x具有两级堆栈,因此在第三个循环中它会溢出,在24条指令中。在20MHz时,它会在1.2微秒和1.5个字节内溢出。
英特尔4004
Intel 4004有一个8位调用子程序指令:
对于与ascii'P'相对应的好奇心。使用3级堆栈,需要24个时钟周期,总共32.4微秒和一个字节。 (除非你超频你的4004 - 来吧,你知道你想要。)
这与befunge答案一样小,但比当前解释器中运行的befunge代码要快得多。
C#:
1
| public int Foo { get { return Foo; } } |
Hoot溢出!
1 2 3 4
| // v___v
let rec f o = f(o);(o)
// ['---']
// -"---"- |
每项任务都需要合适的工具。符合SO溢出语言,经过优化可产生堆栈溢出:
TeX的:
结果是:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| ! TeX capacity exceeded, sorry [input stack size=5000].
~->~
.
~->~
.
~->~
.
~->~
.
~->~
.
~->~
.
...
<*> \def~{~.}~ |
胶乳:
结果是:
1 2 3 4
| ! TeX capacity exceeded, sorry [input stack size=5000].
\end #1->\csname end#1
\endcsname \@checkend {#1}\expandafter \endgroup \if@e...
<*> \end\end |
Z-80汇编程序 - 在内存位置0x0000:
一个字节 - 0xC7 - 将当前PC推送到堆栈并跳转到地址0x0000的无限循环。
另一个PHP示例:
用英语讲:
1
| recursion = n. See recursion. |
BASIC中的以下内容如何:
(我没有BASIC翻译,我担心这是猜测)。
我喜欢Cody的答案堆,所以这是我在C ++中的类似贡献:
1 2 3 4 5 6
| template <int i>
class Overflow {
typedef typename Overflow<i + 1>::type type;
};
typedef Overflow<0>::type Kaboom; |
无论如何都不是代码高尔夫球场,但是,元堆栈的任何东西都会溢出! :-P
这是我的C贡献,重量为18个字符:
尾调优化要困难得多! :-P
使用名为"s.bat"的Window批处理文件:
使用Javascript
为了削减更多的角色,并让自己从更多的软件商店中被踢出来,让我们一起来:
请告诉我"GNU"的缩写。
Groovy的:
$ groovy stack.groovy:
1 2 3 4
| Caught: java.lang.StackOverflowError
at stack.main(stack.groovy)
at stack.run(stack.groovy:1)
... |
1 2 3
| Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky); |
这里希望没有尾递归!
C - 它不是最短的,但它是无递归的。它也不可移植:它在Solaris上崩溃,但是一些alloca()实现可能在这里返回错误(或调用malloc())。对printf()的调用是必要的。
1 2 3 4 5 6 7 8 9 10 11
| #include <stdio.h>
#include
#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
");
return 0;
} |
尝试在一个汉堡上放4个以上的肉饼。堆栈溢出。
perl in 12 chars:
bash in 10 chars(函数中的空格很重要):
Python:
或者:
如果Python优化尾调用...:
我在这篇文章后选择了"最佳答案"。但首先,我要感谢一些非常原始的贡献:
aku的。每一个都探索了一种导致堆栈溢出的新的原始方法。做f(x)的想法? f(f(x))是我将在下一篇文章中探讨的内容。 :-)
Cody是给Nemerle编译器堆栈溢出的一个。
而且(有点勉强),GateKiller是一个关于抛出堆栈溢出异常的人。 :-P
就像我喜欢上述内容一样,挑战在于打高尔夫球,对于受访者来说,我必须对最短的代码(即Befunge入门)给予"最佳答案";我不相信任何人都能击败它(虽然康拉德当然已经尝试过),所以恭喜帕特里克!
看到大量的堆栈溢出递归解决方案,我很惊讶没有人(截至当前的写作)提出Y组合器(参见Dick Gabriel的文章,为什么是Y,作为入门)。我有一个使用Y组合器的递归解决方案,以及aku的f(f(x))方法。 :-)
1
| ((Y (lambda (f) (lambda (x) (f (f x))))) #f) |
这是Scheme中另一个有趣的:
1
| ((lambda (x) (x x)) (lambda (x) (x x))) |
Java的
Java解决方案的版本略微缩短。
1
| class X{public static void main(String[]a){main(a);}} |
3个字节:
更新
根据(旧?)英特尔(?)文档,这也是3个字节:
向前:
在gforth解释器内:
1 2 3 4 5
| : a 1 recurse ; a
*the terminal*:1: Return stack overflow
: a 1 recurse ; a
^
Backtrace: |
在Open Firmware提示符下的Power Mac G4上,这只是挂起机器。 :)
作为C函数中的局部变量:
在Lua:
1
| function f()return 1+f()end f() |
你必须对递归调用的结果做一些事情,否则尾调用优化将允许它永远循环。代码高尔夫很弱,但很高兴!
我想这和冗长的关键词意味着Lua不会很快赢得代码高尔夫。
Java(尴尬):
1 2 3 4 5 6 7 8 9 10 11 12
| public class SO
{
private void killme()
{
killme();
}
public static void main(String[] args)
{
new SO().killme();
}
} |
编辑
当然可以大大缩短:
1 2 3 4 5 6 7
| class SO
{
public static void main(String[] a)
{
main(null);
}
} |
C#
1
| class _{static void Main(){Main();}} |
请注意,我的是一个可编辑的程序,而不仅仅是一个函数。我还删除了多余的空格。
对于天赋,我让班级名称尽可能小。
红宝石:
Ruby,比其他目前更短:
(13个字符)
如果你认为一个调用框架是一个进程,并且堆栈是你的Unix机器,你可以认为一个fork炸弹是一个并行程序来创建一个堆栈溢出条件。试试这个13个字符的bash号码。不需要保存到文件。
在Irssi(基于终端的IRC客户端,而不是"真正"编程语言)中,$ L表示当前命令行。因此,您可以使用以下命令导致堆栈溢出("达到最大递归限制"):
在Scheme中,这将导致解释器耗尽内存:
1 2 3 4
| (define (x)
((x)))
(x) |
批处理程序叫call.cmd;
call call.cmd
1 2 3
| ****** B A T C H R E C U R S I O N exceeds STACK limits ******
Recursion Count=1240, Stack Usage=90 percent
****** B A T C H PROCESSING IS A B O R T E D ****** |
http://www.google.com/search?q=google.com
GWBASIC输出......
1 2 3 4 5 6 7 8 9 10
| OK
10 i=0
20 print i;
30 i=i+1
40 gosub 20
run
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
22 23 24 25 26 27 28 29 30 31 32 33
Out of memory in 30
Ok |
堆栈深度不多:-)
编译:
扩展到:
1 2 3
| main() {
return main()*main();
} |
Java的:
1
| class X{static{new X();}{new X();}} |
实际上导致堆栈溢出初始化X类。在调用main()之前,JVM必须加载类,当它执行此操作时,它会触发任何匿名静态代码块:
如您所见,使用默认构造函数实例化X. JVM甚至会在构造函数之前调用匿名代码块:
哪个是递归部分。
口齿不清
好吧,还没有人提到过Coldfusion,所以...
1
| <cfinclude template="#ListLast(CGI.SCRIPT_NAME,"/")#"> |
那要做到这一点。
C ++编译器错误消息
1
| template<int n>struct f{f<n+1>a;};f<0>::a; |
输出:
1 2 3 4 5
| $ g++ test.cpp;
test.cpp:1: error: template instantiation depth exceeds maximum of 500 (use -ftemplate-depth-NN to increase the maximum) instantiating ‘struct f<500>’
test.cpp:1: instantiated from ‘f<499>’
test.cpp:1: instantiated from ‘f<498>’
...... |
即使编译器通过模板,也会出现下一个错误:缺少main。
除非有一个空程序导致堆栈溢出的语言,否则以下应该是最短的。
Befunge:
一遍又一遍地复制顶部堆栈值。
编辑:
帕特里克更好。使用1s填充堆栈比使用0填充堆栈更好,因为解释器可以优化将0推送到空堆栈作为无操作。
哈斯克尔:
Java:35个字符
我认为为时已晚,但我仍然会发表我的想法:
1
| class A{{new A();}static{new A();}} |
使用静态初始化程序和实例初始化程序功能。
这是我的计算机上的输出(注意它显示了两个错误消息):
1 2 3 4 5
| Exception in thread"main" java.lang.StackOverflowError
at A.<init>(A.java:1)
......
at A.<init>(A.java:1)
Could not find the main class: A. Program will exit. |
另见:http://download.oracle.com/docs/cd/E17409_01/javase/tutorial/java/javaOO/initial.html
CIL / MSIL:
对象代码:
PostScript,7个字符
在GhostScript中运行时,抛出此异常:
1 2 3 4 5 6 7 8 9 10 11
| GS>{/}loop
Error: /stackoverflow in --execute--
Operand stack:
--nostringval--
Execution stack:
%interp_exit .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- %loop_continue 1753 2 3 %oparray_pop --nostringval-- --nostringval-- false 1 %stopped_push .runexec2 --nostringval-- --nostringval-- --nostringval-- 2 %stopped_push --nostringval-- --nostringval-- %loop_continue
Dictionary stack:
--dict:1150/1684(ro)(G)-- --dict:0/20(G)-- --dict:70/200(L)--
Current allocation mode is local
Last OS error: 11
Current file position is 8 |
这是不使用变量的递归版本(51个字符):
1
| [{/[aload 8 1 roll]cvx exec}aload 8 1 roll]cvx exec |
PIC18:
overflow
BLOCKQUOTE>
在Whitespace,我想:
它可能不会出现。 :/
F#
人们不断问"F#对什么有用?"
性能优化版本(将失败更快:))
Groovy(5B):
C#
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class Program
{
class StackOverflowExceptionOverflow : System.Exception
{
public StackOverflowExceptionOverflow()
{
throw new StackOverflowExceptionOverflow();
}
}
static void Main(string[] args)
{
throw new StackOverflowExceptionOverflow();
}
} |
我意识到这不是最短的(甚至代码高尔夫它也不会接近于接近短路),但我简直无法拒绝抛出一个异常,抛出时抛出stackoverflowexception,然后才能终止运行时本身^^
JavaSript:
Huppies回答一句话:
1
| (function i(){ i(); })() |
相同数量的字符,但没有新行:)
一个更好的lua解决方案:
将其粘贴到SciTE或交互式命令提示符中然后调用它。繁荣!
我在E2上的无限循环中有一个列表 - 只看标题中标记为"Stack Overflow"的那些。
我认为最短的是
在直流。 False可能有一个较短的解决方案。
编辑:显然这不起作用......至少在GNU DC上。也许是在BSD版本上。
在汇编语言中(x86处理器,16位或32位模式):
这会产生:
在C / C ++中:
1 2 3
| int main( ) {
return main( );
} |
so.c,共15个字符:
结果:
1 2 3
| antti@blah:~$ gcc so.c -o so
antti@blah:~$ ./so
Segmentation fault (core dumped) |
编辑:好的,它使用-Wall发出警告,并且不会导致堆栈溢出-O2。但它的确有效!
Java(X.java的完整内容):
1 2 3 4
| class X {
public static void main(String[] args) {
main(null);
}} |
考虑到所有的语法糖,我想知道是否可以用Java做更短的。任何人?
编辑:哎呀,我错过了已经发布的几乎相同的解决方案。
编辑2:我会说,这个(性格明智)是最短的
1
| class X{public static void main(String[]a){main(null);}} |
编辑3:感谢Anders指出null不是最佳参数,因此它更短:
1
| class X{public static void main(String[]a){main(a);}} |
c#再次:
1
| class Foo { public Foo() {new Foo(); } } |
包含换行符的10个字符的Shell脚本解决方案:
好吧,技术上不是堆栈溢出,但逻辑上是这样,如果你考虑产生一个新进程作为构建一个新的堆栈帧。
结果:
1 2
| antti@blah:~$ ./so
[disconnected] |
哎呦。注意:不要在家里试试
完成Delphi程序。
1 2 3 4 5 6 7
| program Project1;
{$APPTYPE CONSOLE}
uses SysUtils;
begin
raise EStackOverflow.Create('Stack Overflow');
end. |
GNU make:
使用以下内容创建名为"Makefile"的文件:
然后运行make:
请注意,必须使用制表符来偏移单词"make"。此文件为9个字符,包括2个行尾字符和1个制表符。
我想你可以用bash做类似的事情,但它可能太容易让人感兴趣:
创建文件名"b"并将其标记为可执行文件(chmod + x b):
1
| b ## ties the winning entry with only one character (does not require end-of-line) |
现在用。执行文件
很难说这种方法在技术上是否会导致堆栈溢出,但它确实构建了一个堆栈,这个堆栈会一直增长,直到机器耗尽资源。使用GNU make做的很酷的事情是,你可以在构建和销毁堆栈时观察它的输出状态信息(假设你在崩溃发生之前的某个时刻点击^ C)。
可以编译K&amp; R C中的简短解决方案:
14个字节
这是另一个Ruby答案,这个使用lambdas:
。
in perl:
事实上,这将适用于任何支持backquote-command语法的shell,并将自己的名称存储在$0中
JavaScript中的另一个:
1
| (function() { arguments.callee() })() |
不会是最短的,但我必须尝试一下...... C#
string [] f = new string [0];主(F);
有点短
1
| static void Main(){Main();} |
假:
[1] [1]#
(False是一种堆栈语言:#是一个while循环,需要2个闭包,一个条件和一个正文。正文是导致溢出的一个)。
1 2 3 4 5 6
| /* In C/C++ (second attempt) */
int main(){
int a = main() + 1;
return a;
} |
CMD溢出一行
1
| echo @call b.cmd > b.cmd & b |
在哈斯克尔
这试图找到(1+)函数(λ n → n + 1)的修正点。修复的实现是
1
| fix f = (let x = f(x) in x) |
所以
变
注意
只是循环。
PHP是递归的缩写
为了回应Y组合者的评论,我也可以通过SKI演算中的Y-combinator:
1
| S (K (S I I)) (S (S (K S) K) (K (S I I))) |
我不知道有任何SKI口译员,但我曾在动作脚本中写了大约一个小时的图形口译员。我愿意发布是否有兴趣(虽然我从来没有让布局工作得非常有效)
在这里阅读所有相关内容:
http://en.wikipedia.org/wiki/SKI_combinator_calculus
电源外壳
$f={&$f};&$f
"由于呼叫深度溢出,脚本失败。呼叫深度达到1001,最大值为1000。"
TCL:
我没有可以进行尾递归的tclsh解释器,但这可能会欺骗这样的事情:
已经有一个perl,但这是一个短的几个字符(9对12) - 它不会递归:)
s//*_=0/e
VB6
1 2 3 4 5 6 7
| Public Property Let x(ByVal y As Long)
x = y
End Property
Private Sub Class_Initialize()
x = 0
End Sub |
C ++:
1 2 3 4
| int overflow(int n)
{
return overflow(1);
} |
PHP - 递归只是为了好玩。我想需要一个PHP解释器将它从运行中取出,但是嘿 - 它会导致崩溃。
1
| function a() { a(); } a(); |
在单元spus上,没有堆栈溢出,因此不需要递归,我们只需擦除堆栈指针即可。
asm("andi $ 1,$ 1,0");
递归是旧帽子。这是相互递归。通过调用任一功能开始。
1 2 3 4 5 6 7 8
| a()
{
b();
}
b()
{
a();
} |
PS:但是你要求最短路..不是最有创意的方式!
JavaScript(17字节)
VB脚本(25字节)
1
| t="Execute(t)":Execute(t) |
Dyalog APL
1 2 3 4
| fib←{
??0 1:?
+/?¨?-1 2
} |
1 2 3 4
| int main(){
int a = 20;
return main();
} |
哈斯克尔:
1
| main = print $ x 1 where x y = x y + 1 |
JavaScript的:
1 2
| function i(){ i(); }
i(); |
C ++
使用函数指针:
1 2 3 4
| int main(){
int (*f)() = &main;
f();
} |
号角:
Python:
1 2 3 4 5
| import sys
sys.setrecursionlimit(sys.maxint)
def so():
so()
so() |
Fortran,13和20个字符
要么
第二种情况是依赖编译器的;对于GNU Fortran,需要使用-fno-underscoring进行编译。
(两个计数都包括所需的换行)
C#,以20个字符(exclusing whitespace)完成:
1 2 3
| int s(){
return s();
} |
1
| int main(void) { return main(); } |
我试着在Erlang中做到这一点:
1 2
| c(N)->c(N+1)+c(N-1).
c(0). |
双重调用本身会使内存使用量增加O(n^2)而不是O(n)。
然而,Erlang解释器似乎没有崩溃。
VB.Net
1 2 3
| Function StackOverflow() As Integer
Return StackOverflow()
End Function |
动作脚本3:全部用数组完成......
1 2 3
| var i=[];
i[i.push(i)]=i;
trace(i); |
也许不是最小的,但我觉得它很可爱。特别是push方法返回新的数组长度!
在名为so.ps的PostScript文件中,将导致execstackoverflow
1 2 3 4
| %!PS
/increase {1 add} def
1 increase
(so.ps) run |
为什么不
(堆栈长大)
在C#中,这将创建一个stackoverflow ...
1 2 3 4
| static void Main()
{
Main();
} |
序言
在咨询时,该程序会使SWI-Prolog和Sicstus Prolog崩溃。
Ruby,尽管不是那么简短:
1 2 3 4 5 6 7
| class Overflow
def initialize
Overflow.new
end
end
Overflow.new |
我认为这是我以前从未玩过的作弊;)但是这里有
8086汇编程序:
org Int3VectorAdrress;是作弊吗?
int 3
1个字节 - 或5个字符生成代码,你说什么?
尾调用优化可以通过尾调用来破坏。在Common Lisp中:
不是很短,但有效! (JavaScript的)
1
| setTimeout(1, function() {while(1) a=1;}); |
为了好玩,我不得不查看Motorolla HC11组装:
1 2 3
| org $100
Loop nop
jsr Loop |
带有27个非空白字符的C# - 包括调用。
1 2 3
| Action a = null;
a = () => a();
a(); |
1 2 3 4 5 6 7
| //lang = C++... it's joke, of course
//Pay attention how
void StackOverflow(){printf("StackOverflow!");}
int main()
{
StackOverflow(); //called StackOverflow, right?
} |
在x86汇编中,在中断处理程序的内存中的位置处除以0指令除以0!
Perl在10个字符中
最终耗尽所有可用内存。
MS-DOS批处理:
1 2 3 4
| copy CON so.bat
so.bat
^Z
so.bat |
另一个Windows批处理文件:
D中的元问题:
1 2
| class C(int i) { C!(i+1) c; }
C!(1) c; |
编译时堆栈溢出
简单而美好C.感觉非常直观。
OCaml的
这个有点不同。堆栈上只有一个堆栈帧(因为它的尾递归),但它的输入会一直增长,直到它溢出堆栈。只需使用非空列表调用f(在解释器提示符下):
1 2
| # f [0];;
Stack overflow during evaluation (looping recursion?). |
红宝石(再次):
1
| def a(x);x.gsub(/./){a$0};end;a"x" |
已经有很多ruby解决方案,但我认为我会投入一个正则表达式。
bash:只有一个进程
1 2 3
| \#!/bin/bash
of() { of; }
of |
几乎任何外壳:
(5个字符,仅在从文件运行时有效)
Z80汇编语言......
1 2
| .org 1000
loop: call loop |
这会在1000位置生成3个字节的代码....
1000 CD 00 10
即使它没有真正的堆栈......
brainf * ck 5 char
16位asm中的五个字节会导致堆栈溢出。
序言
p :-P。
= 5个字符
然后启动它并查询p
我认为这是非常小的,并在prolog中耗尽。
只查询swi prolog中的变量会产生:
?- X。
%...... 1,000,000 ............ 10,000,000年后
%
%>> 42 <<(上次发布给出的问题)
这是另一个bash fork炸弹:
:(){:|:&amp; } ;:
我认为这将在Java中工作(未经验证):
1 2
| enum A{B.values()}
enum B{A.values()} |
如果由于缺少main(String [])而导致失败的机会在静态初始化之前应该溢出。
红宝石:
(17个字符)
1
| Redmond.Microsoft.Core.Windows.Start() |
哎呀,我不知道,我从来没有编写导致Stack Overflow的代码;)