产生堆栈溢出的最奇怪的方法


146

作为程序员,您当然知道由于明显的递归而导致的堆栈溢出错误。但是,当然有很多怪异和不寻常的方法可以使您喜欢的语言吐出该错误。

目标:

  1. 必须引起堆栈溢出,该堆栈溢出在错误输出中清晰可见。
  2. 不允许使用明显的递归。

无效程序的示例:

// Invalid, direct obvious recursion.
methodA(){ methodA(); }
// Invalid, indirect, but obvious recursion.
methodA(){ methodB(); }
methodB(){ methodA(); }

最有创意的方式是最好的,因为这是一场。也就是说,避免无聊的答案是这样的:

throw new StackOverflowError(); // Valid, but very boring and downvote-deserving.

即使我现在接受了答案,也可以添加更多答案:)


14
我倾向于通过导航到stackoverflow.com进行生产,尽管众所周知,我会在选择的搜索引擎上查询“堆栈溢出”。
OJFord 2014年

21
使用Internet Explorer。抓住一个肯定的方法:)
asgoth 2014年

64
产生堆栈溢出的最奇怪的方法是在codegolf.stackexchange.com上发布一个流行度竞赛,要求人们发布产生堆栈溢出的最奇怪的方法。响应者在测试问题解决方案时,将产生堆栈溢出。我还没有测试过,所以不能确定它是否有效(这就是为什么我没有将其发布为答案)。
Tim Seguine 2014年


11
驾驶丰田(嘿,等等,我的车丰田...)
吱吱作响的ossifrage

Answers:


225

蟒蛇

import sys
sys.setrecursionlimit(1)

这将导致解释器立即失败:

$ cat test.py
import sys
sys.setrecursionlimit(1)
$ python test.py
Exception RuntimeError: 'maximum recursion depth exceeded' in <function _remove at 0x10e947b18> ignored
Exception RuntimeError: 'maximum recursion depth exceeded' in <function _remove at 0x10e8f6050> ignored
$ 

它不使用递归,而只是收缩堆栈,因此它将立即溢出。


12
可爱,但我认为原始问题的目的并不完全是。
Nit

12
@Nit我看不到问题。该解决方案不能令人满意吗?
SimonT

17
@ masterX244是的,问题的全部重点是“不要按常规方式进行”。
Plutor

24
@Plutor您通常是故意设置StackOverFlow吗?
2014年

15
第一次发布时只是有点聪明。
primo 2014年


131

C / Linux 32位

void g(void *p){
        void *a[1];
        a[2]=p-5;
}
void f(){
        void *a[1];
        g(a[2]);
}
main(){
        f();
        return 0;
}

通过覆盖返回地址来工作,因此g返回到main调用之前的位置f。适用于返回地址在堆栈上的任何平台,但可能需要进行调整。

当然,在数组外部进行写操作是未定义的行为,您无法保证会导致堆栈溢出,而不是将胡须涂成蓝色。平台,编译器和编译标志的详细信息可能会有很大的不同。


1
这不会产生段错误吗?
2014年

4
+1为怪异的堆栈操作,绝对没有递归!
RSFalcon7 2014年

6
@ 11684,这是未定义的行为,因此通常会崩溃。在我测试过的32位Linux上,它在数组外部进行写操作,覆盖返回地址,并且直到堆栈溢出后才崩溃。
ugoren 2014年

46
“把你的胡子涂成蓝色”->那条线吸引了我。
Aneesh Dogra 2014年

2
哇。这非常令人困惑。
MirroredFate 2014年

108

JavaScript / DOM

with (document.body) {
    addEventListener('DOMSubtreeModified', function() {
        appendChild(firstChild);
    }, false);

    title = 'Kill me!';
}

如果您想杀死浏览器,请在控制台中尝试一下。


53
我确定您应该获得更多的+1票,但可悲的是人们在投票之前就进行了尝试。...大声笑
Reactgular 2014年

5
好吧,那很有效。我什至无法打开任务管理器来杀死它。
primo 2014年

1
使用Chrome,关闭标签。问题解决了。
科尔·约翰逊

1
with (document.body) { addEventListener('DOMSubtreeModified', function() { appendChild(firstChild); }, false); title = 'Kill me!'; } 15:43:43.642 TypeError: can't convert undefined to object
Brian Minton

1
该死的我的Firefox被绞死了
Farhad 2014年

91

爪哇

在这里某处看到这样的东西:

编辑:找到我在哪里看到:乔K对引发StackOverflow错误的最短程序的答案

public class A {
    String val;
    public String toString() {
        return val + this;
    }

    public static void main(String[] args) {
        System.out.println(new A());
    }
}

这会使一些Java初学者感到困惑。它只是隐藏了递归调用。val + this成为val + this.toString()因为val是一个字符串。

看到它在这里运行:http : //ideone.com/Z0sXiD


30
实际上,确实如此new StringBuilder().append(val).append("").append(this).toString(),最后一个追加调用String.valueOf(...),后者又调用toString。这使您的堆栈跟踪有些变化(其中有三种方法)。
圣保罗Ebermann

2
@PaŭloEbermann是的,这是正确的。但是,说它变得容易得多"" + this.toString()
贾斯汀

2
我认为这+ "" +可能会让人们失望,因为乍看之下它似乎毫无用处。String val;并且return val + this;可能略有偷偷摸摸
Cruncher

@Cruncher一点也不。如果您是Java编码人员,您会知道,在""-String构造过程中将int连接到字符串的简单方法是+ ""
Justin

5
在真实的应用程序中,我希望避免无限递归和堆栈溢出错误
jon_darkstar 2014年

77

C

很简单:

int main()
{
    int large[10000000] = {0};
    return 0;
}

10
+1不明显!尽管它非常依赖ulimit -s unlimited于系统(在Linux中外壳程序可以解决此问题)
RSFalcon7 2014年

4
@ RSFalcon7,谢谢+1,但是对我来说,这实际上是最明显的!!
Shahbaz 2014年

14
@Cruncher:它不会导致递归。给出的问题是炸毁堆栈。在许多操作系统上,堆栈是固定大小的,并且远远小于一千万个整数,因此这使堆栈不堪重负。
埃里克·利珀特

2
@HannoBinder,在我测试过的Linux中,没有堆栈溢出错误。您会遇到分段错误,因为堆栈溢出会导致访问未拥有的分段。我不确定在Linux中是否甚至存在堆栈溢出错误,因为无限递归函数调用还会产生分段错误。
Shahbaz 2014年

3
~0u是C.一个相当大量的
Vortico

63

C中的非递归堆栈溢出

调用约定不匹配。

typedef void __stdcall (* ptr) (int);

void __cdecl hello (int x) { }

void main () {
  ptr goodbye = (ptr)&hello;
  while (1) 
    goodbye(0);
}

用编译gcc -O0

__cdecl函数希望调用者清理堆栈,并__stdcall希望被调用者这样做,因此通过类型转换函数指针进行调用,清理永远不会完成- main将参数推送到每次调用的堆栈上,但不会弹出,最终堆栈填充。


2
向堆栈发送垃圾邮件的好方法:P
masterX244,2014年

62

的JavaScript

window.toString = String.toLocaleString;
+this;

5
这一点被低估了。
Ry-

1
怎么+this办?
NobleUplift 2014年

8
一元+调用ToNumber抽象操作。该操作使用具有数字提示类型的ToPrimitive操作。对象上的ToPrimitive使用[[DefaultValue]]内部方法,该方法在传递数字提示时首先会检查valueOf()方法是否存在并返回原语。window.valueOf()返回一个对象,因此[[DefaultValue]]返回调用toString()的结果。window.toString要做的第一件事(现在是toLocaleString)是在“ this”上调用toString的。重复。
Ryan Cavanaugh 2014年

3
如果Chrome抛出错误“太多的递归”,那么它就可以在Chrome上正常工作,对吗?堆栈溢出,这就是Chrome传递堆栈溢出异常的方式。
戴维·康拉德

4
您应该使用+{toString:"".toLocaleString}:-)
Bergi 2014年

62

我对Java 7和Java 8不受我先前回答中的恶意代码的困扰而感到沮丧。因此,我认为有必要为此添加一个补丁。

成功!我printStackTrace()扔了一个StackOverflowErrorprintStackTrace()通常用于调试和日志记录,没有人合理地怀疑它可能很危险。不难看出该代码可能会被滥用以产生一些严重的安全问题:

public class StillMoreEvilThanMyPreviousOne {
    public static void main(String[] args) {
        try {
            evilMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void evilMethod() throws Exception {
        throw new EvilException();
    }

    public static class EvilException extends Exception {
        @Override
        public Throwable getCause() {
            return new EvilException();
        }
    }
}

有人可能认为这是显而易见的递归。它不是。该EvilException构造函数不调用getCause()方法,使异常实际上可以安全地毕竟抛出。调用该getCause()方法将不会导致StackOverflowError两者之一。递归位于JDK的正常printStackTrace()行为之外,以及用于检查异常的用于调试和日志记录的任何第三方库。此外,抛出异常的位置可能与处理异常的位置相距甚远。

无论如何,这里的代码确实会引发,并且根本不StackOverflowError包含任何递归方法调用。在StackOverflowError外面发生的main方法,在JDK的UncaughtExceptionHandler

public class StillMoreEvilThanMyPreviousOneVersion2 {
    public static void main(String[] args) {
        evilMethod();
    }

    private static void evilMethod() {
        throw new EvilException();
    }

    public static class EvilException extends RuntimeException {
        @Override
        public Throwable getCause() {
            return new EvilException();
        }
    }
}
Exception: java.lang.StackOverflowError thrown from the UncaughtExceptionHandler in thread "main"

2
:D,现在具有跨Java版本stackoverflow兼容方法。邪恶的混蛋!:D
Kiwy 2014年

9
我倾向于认为这种情况下的递归很明显。
塔伊米尔2014年

1
@BlacklightShining调用该getCause()方法不会导致StackOverflowError。它依赖于以下事实:有一个JDK的代码递归地调用该getCause()方法。
Victor Stafusa 2014年

2
我想你可以通过改变身体简化这getCause只是return this;但显然Java是太聪明了。它注意到它是一个“ CIRCULAR REFERENCE”。
戴维·康拉德

1
我没有得到,StackOverflowError因为jdk-1.7.0.21p2v0的OpenBSD 5.5软件包有一个错误。它不会抛出StackOverflowError。它击中了SIGSEGV核心。
kernigh 2014年

57

Linux x86 NASM组装

section .data
    helloStr:     db 'Hello world!',10 ; Define our string
    helloStrLen:  equ $-helloStr       ; Define the length of our string

section .text
    global _start

    doExit:
        mov eax,1 ; Exit is syscall 1
        mov ebx,0 ; Exit status for success
        int 80h   ; Execute syscall

    printHello:
        mov eax,4           ; Write syscall is No. 4
        mov ebx,1           ; File descriptor 1, stdout
        mov ecx,helloStr    ; Our hello string
        mov edx,helloStrLen ; The length of our hello string
        int 80h             ; execute the syscall

    _start:
        call printHello ; Print "Hello World!" once
        call doExit     ; Exit afterwards

扰流板:

忘记了从printHello返回,因此我们再次跳入_start。


78
在组装中,没有什么是显而易见的。
1684年

21
@ 11684:我发现相反的事实是正确的:在汇编中,一切都是显而易见的,因为没有人可以使用抽象来隐藏其代码的实际作用。
梅森惠勒

3
这以其简洁和优雅而著称。
haneefmubarak

11
@MasonWheeler:我想说的是一切都是可见的,而不是显而易见的……要了解可见与明显之间的区别的一种好方法,我喜欢引用underhanded.xcott.com
Olivier Dulac

2
我记得我经常忘记的错误ret
Ruslan 2014年

48

编译时使用C ++

template <unsigned N>
struct S : S<N-1> {};

template <>
struct S<0> {};

template
struct S<-1>;
$ g ++ -c test.cc -ftemplate-depth = 40000
g ++:内部编译器错误:分段错误(程序cc1plus)
请提交完整的错误报告,
如果合适,请使用预处理的源。
有关说明,请参见。

此源文件没有递归,没有一个类本身具有基类,甚至没有间接的基类。(在C ++中,在这样的模板类中,S<1>并且S<2>是完全不同的类。)分段错误是由于在编译器中递归之后的堆栈溢出引起的。


7
我承认我会在您的元程序中将其称为明显的递归。
2014年

2
GCC检测到递归并优雅地停止了这一面(4.8及以上似乎很好)
Alec Teal 2014年

2
template <typename T> auto foo(T t) -> decltype(foo(t)); decltype(foo(0)) x;有点短。
Casey 2014年

2
@hvd似乎正在利用GCC中的错误。clang捕获了错误的用法 -我想您已经知道了-但它使我的GCC发出了将近2 MB的错误消息。
Casey 2014年


45

重击(危险警报)

while true
do 
  mkdir x
  cd x
done

严格来说,这不会直接导致堆栈溢出,但会生成可能被标记为“ 持久性堆栈溢出生成情况 ”:当您运行此操作直到磁盘已满时,并希望使用“ rm -rf”消除混乱x”,表示已命中。

但是,并非所有系统都这样。有些比其他的更健壮。

大危险警告:

某些系统处理起来非常糟糕,您可能很难清理(因为“ rm -rf”本身会遇到响应问题)。您可能必须编写类似的脚本来进行清理。

如果不确定,最好在暂存VM中尝试。

PS:当然,如果以批处理脚本编程或完成,则同样适用。
PPS:获得您的评论,您的特定系统的行为方式可能会很麻烦...


如我所写:在许多系统上,rm -rf尝试掉下来并被一个击中(这些天,也许不再使用64位地址空间了-但是在具有较小堆栈的小型计算机上可能会)。当然,周围也可能会有“ rm”实现,它们的执行方式有所不同...
blabla999 2014年

2
在我看来,while cd x; do :; done; cd ..; while rmdir x; cd ..; done;应该采取一些措施。
Blacklight Shining

您绝对正确(这就是我所说的“类似的清理脚本”的意思)。但是,一旦磁盘(或配额)已满,您可能甚至很难登录,因为某些系统过去曾严重处理这种情况。您必须以root用户身份进入并执行脚本(在当今的PC上这很容易,但是在古代,当计算机由多个用户使用时,这通常很难)。
blabla999

有趣的是,这比下面的Smalltalk魔术获得更多的选票(从未想过!)
blabla999

有人在Windows上尝试过吗?
Sarge Borsch

43

爪哇

Java Puzzlers的一个不错的选择。它打印什么?

public class Reluctant {
    private Reluctant internalInstance = new Reluctant();

    public Reluctant() throws Exception {
        throw new Exception("I'm not coming out");
    }

    public static void main(String[] args) {
        try {
            Reluctant b = new Reluctant();
            System.out.println("Surprise!");
        } catch (Exception ex) {
            System.out.println("I told you so");
        }
    }
}

实际上,它失败并显示StackOverflowError。

构造函数中的异常只是一个红色鲱鱼。这是书上要说的:

调用构造函数时,实例变量初始化程序在构造函数的主体之前运行。在这种情况下,变量的初始化程序将internalInstance递归调用构造函数。反过来,该构造函数internalInstance通过再次调用Reluctant构造函数等来无限期地初始化其自己的 字段。这些递归调用会导致 StackOverflowError构造函数主体有机会执行之前。因为StackOverflowErrorError而不是 的子类型Exception,所以中的catch子句main不会捕获它。


41

胶乳

\end\end

输入堆栈溢出,因为\end反复膨胀本身无限循环,如解释在这里

TeX失败,出现TeX capacity exceeded, sorry [input stack size=5000]或类似符号。


1
我在等待TeX / LaTeX问题。这些事情比大多数事情更具挑战性-通常,我忘记了我正在做的事情突然间设法写出了无限递归的东西,这算是编程。
Ernir 2014年


1
“超出了TeX的容量,很抱歉” TeX失败时非常礼貌。
Alex A.

40

高炉

最终将使堆栈溢出,仅取决于解释程序使堆栈多长时间...

+[>+]

5
该代码使我想起了人生的游戏。
亚当·阿罗德

10
严格来说,头脑干没有任何意义。
fejesjoco 2014年

6
@fejesjoco磁带,如果您愿意。
Timtech

32

C#,在编译时

有多种方法可以使Microsoft C#编译器崩溃。每当您看到C#编译器的“表达式过于复杂而无法编译”错误时,几乎可以肯定是因为堆栈已损坏。

解析器是递归下降的,因此任何深度嵌套的语言结构都将破坏堆栈:

 class C { class C { class C { ....

表达式解析器非常聪明,可以消除通常递归的那一侧的递归。通常:

x = 1 + 1 + 1 + 1 + .... + 1;

它构建了一个非常深的解析树,不会破坏堆栈。但是,如果您强制递归发生在另一侧:

x = 1 + (1 + (1 + (1 + ....+ (1 + 1))))))))))))))))))))))))))))))))))))))))))...;

然后可以将堆栈吹散。

这些具有程序非常大的特性。也有可能使语义分析器使用一个小的程序进入无限的递归,因为它不够智能,无法删除类型系统中的某些奇数循环。(罗斯林可能会改善这一点。)

public interface IN<in U> {}
public interface IC<X> : IN<IN<IC<IC<X>>>> {}
...
IC<double> bar = whatever;
IN<IC<string>> foo = bar;  // Is this assignment legal? 

我在这里描述了为什么这种分析进行无限递归:

http://blogs.msdn.com/b/ericlippert/archive/2008/05/07/covariance-and-contravariance-part-twelve-to-infinity-but-not-beyond.aspx

对于更多有趣的示例,您应该阅读本文:

http://research.microsoft.com/en-us/um/people/akenn/generics/FOOL2007.pdf


2
确切的错误消息是fatal error CS1647: An expression is too long or complex to compile near (code)。此错误消息的文档在此处,并且与您所说的完全一样:“在编译器中,处理您的代码时发生堆栈溢出。”
bwDraco

32

在互联网上 (每天有十亿人使用)

Redirects, HTTP status code: 301

例如,在Dell支持网站上(无罪,对不起Dell):

如果从URL中删除了支持TAG,那么它将进入 无限重定向。在以下URL中,######是任何支持TAG。

http://www.dell.com/support/drivers/uk/zh-CN/ukdhs1/ServiceTag/#######ss=BSD&~ck=mn

我相信这相当于堆栈溢出。


5
好方法:) firefox告诉它重定向,因此请求无法解决,这是stackoverflow rquivalent的:)
masterX244

3
请注意,重定向不是无限的-如果您单击“重试”,它将/Errors/向URL 添加更多的,然后在收到HTTP 400错误请求后停止。但这可以说比无限重定向更好地实现了堆栈溢出。
nandhp

@nandhp,我同意,但是如果您认为第三世界的浏览器(不是现代的,IE等),则他们对这种情况一无所知。
codeSetter 2014年

2
Wget在这里的回应方式是:pastebin.com/pPRktM1m
bwDraco 2014年

1
http://www.dell.com/support/drivers/uk/en/ukdhs1/ServiceTag/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/Errors/...
Vortico 2014年

31

的PHP

仅使用循环元素完成的stackoverflow。

$a = array(&$a);
while (1) {
    foreach ($a as &$tmp) {
        $tmp = array($tmp, &$a);
    }
}

说明(悬停以查看扰流板):

当解释器尝试将$tmp数组垃圾回收时(在$tmp此处重新分配时),该程序将出现段错误。仅仅因为数组太深(自引用),然后垃圾回收器最终以递归的形式结束。


16
PHP的GC无法检测自引用结构?真?!哎哟。那邪恶的。
Peter C

1
是的,但这并不完美。while (1) { $a = array(&$a); }
出于

是的,我认为这也是PHP在面向对象开发方面也无法正常工作的原因。(抽象,继承等)
pythonian29033

1
@ pythonian29033关心详细吗?
vvondra 2014年

30

爪哇

我做的恰恰相反–一个程序显然应该引发堆栈溢出错误,但是没有。

public class Evil {
    public static void main(String[] args) {
        recurse();
    }

    private static void recurse() {
        try {
            recurse();
        } finally {
            recurse();
        }
    }
}

提示:程序运行时间为O(2 n),n是堆栈的大小(通常为1024)。

来自Java难题者#45:

假设我们的机器每秒可以执行10 10 调用并每秒生成10 10个异常,这在当前标准下是相当慷慨的。根据这些假设,该程序将在大约1.7×10 291年内终止。从这个角度来看,我们的太阳寿命估计为10 10年,因此可以肯定的是,我们谁也不会看到这个程序终止。尽管它不是无限循环,但也可能是无限循环。


3
明显的递归...不是很有趣。
卡米2014年

5
@Kami你试过了吗?您实际上收到了StackOverflowError吗?似乎很明显,但事实并非如此。
ntoskrnl 2014年

仅仅因为捕获到异常并不意味着它从未被抛出。该程序在时间O(n)之后引发堆栈溢出异常
CodesInChaos

1
@CodesInChaos好的,所以我仔细检查了一下,正确的版本使用finally而不是catch,运行时间为O(2 ^ n)。答案已更新。
ntoskrnl 2014年

@ntorkrnl好人+1; btw已使编译器进入stackoverflow(编译器在VM内运行,也很方便)
masterX244

30

C#

第一篇文章,所以请对我轻松一点。

class Program
{
    static void Main()
    {
        new System.Diagnostics.StackTrace().GetFrame(0).GetMethod().Invoke(null, null);
    }
}

这只是创建一个堆栈跟踪,获取顶部框架(这是我们对的最后一次调用Main()),获取方法,然后调用它。


很好的自我调用方式,如果没有解释就不会显而易见;+1
masterX244

您应该用“可能出什么问题?”来注释该代码:P
Spaceman,2015年

26

爪哇

  • 在Java 5中,printStackTrace()进入无限循环。
  • 在Java 6中,printStackTrace()throws StackOverflowError
  • 在Java 7和8中,此问题已修复。

疯狂的是,在Java 5和6中,它不是来自用户代码,而是发生在JDK的代码中。没有一个合理的嫌疑人可能printStackTrace()会被处决。

public class Bad {
    public static void main(String[] args) {
        try {
            evilMethod();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private static void evilMethod() throws Exception {
        Exception a = new Exception();
        Exception b = new Exception(a);
        a.initCause(b);
        throw a;
    }
}

7
是的 万无一失的stackoverflows是进行代码拖曳的最佳朋友,并且是狩猎em的严重头疼
masterX244 2014年

2
如果有人想知道,C#中的等效代码会导致无限循环。但是InnerException属性是只读的,并且是在构造函数中设置的,因此需要反射才能导致此情况。
Athari 2014年

17

JavaScript:非递归的迭代函数变异

var f = function() {
    console.log(arguments.length);
};

while (true) {
    f = f.bind(null, 1);
    f();
}

这里根本没有递归。f它将反复使用越来越多的参数,直到它可以在单个函数调用中使堆栈溢出console.log如果要查看执行此操作需要多少个参数,则该部分是可选的。它还确保了聪明的JS引擎不会对此进行优化。

CoffeeScript中的代码高尔夫球版本,28个字符:

f=->
do f=f.bind f,1 while 1

14

具有史诗般失败的C#

using System.Xml.Serialization;

[XmlRoot]
public class P
{
    public P X { get { return new P(); } set { } }
    static void Main()
    {
        new XmlSerializer(typeof(P)).Serialize(System.Console.Out, new P());
    }
}

失败的方式是史诗般的,它使我完全震惊:

在此处输入图片说明

它只是一系列看似无限的奇怪图像的一帧。

这一定是有史以来最奇怪的事情。有人可以解释吗?显然,用于缩进的空间的不断增加导致这些白色块出现。它发生在带有.NET 4.5的Win7 Enterprise x64上。

我还没有真正看到结局。如果替换System.Console.OutSystem.IO.Stream.Null,它会很快消失。

解释很简单。我创建一个具有单个属性的类,并且该类始终返回其包含类型的新实例。因此,这是一个无限深的对象层次结构。现在,我们需要一些可以尝试通读的内容。那是我使用的地方XmlSerializer,它就是这样做的。显然,它使用递归。


是的 序列化ftw:P; 但更有趣的是,当您的怪癖完全不在代码中时,例如snakeyaml如何获取属性,而一个类以无休止的递归方式返回自己
masterX244 2014年

1
好吧,溢出确实发生在我的代码之外,但是我发布此消息的真正原因是由于控制台中的意外副作用:-)
fejesjoco 2014年

我认为,白位必须与.Net 4.5或环境的设置有关,因为使用.Net 4(即使通过cmd运行)也只能获得空格,而不会出现白色块。我的猜测是Win7 Enterprise版本的cmd或.Net 4.5控制台仿真器都将某种字符组合视为“更改控制台颜色背景”。
法拉普

我无法在启用了Aero的Win7 x64 Professional上使用.NET 4.5复制它
2014年

也无法复制。.NET 4.5,Windows 8.1 Pro。
bwDraco

13

重击

_(){ _;};_

尽管许多人可能认识到递归是显而易见的,但它看起来很漂亮。没有?

执行后,可以保证看到:

Segmentation fault (core dumped)

5
这个更漂亮或更糟:_(){_|_;};_
RSFalcon7

1
@ RSFalcon7 Forkbomb警报!(此外,{语法上是否需要空格?)
Blacklight Shining

3
也尝试一下:(){:|:;}:
Tarek Eldeeb 2014年

14
看起来像一个令人毛骨悚然的突变图释。
Tim Seguine 2014年

8
重击表情:吃脸的人,杀手的堆栈。
NobleUplift

12

哈斯克尔

(很遗憾,但直到至少ghc-7.6,它都是正确的,尽管使用O1或更多它会解决问题)

main = print $ sum [1 .. 100000000]

它不应该自动进行尾部调用优化吗?
blabla999

2
@ blabla999:在Haskell中,尾声调用并不重要,主要是由于隐藏的懒惰导致此类问题而导致的大量堆积。在这种情况下,问题是使用sum来实现的foldl,它确实使用了尾部调用,但是由于它不评估累加器,因此严格地只会产生一堆与原始列表一样大的thunk。切换到时foldl' (+),问题消失了,该问题得到严格评估,因此在其尾部调用中返回WHN。或者,正如我所说,如果您启用GHC的优化!
停止了逆时针旋转

aah-很有意思,因此,如果没有人等待大块的东西(即不打印),垃圾收集器会将它们收集起来(从前到后)?
blabla999

1
顺便说一句,Haskell标准并未真正指定所有这些:仅要求评估是非严格的,即,如果不完全需要结果,则无限终止计算不会永远阻塞。它真正阻塞的时间取决于实现,在标准的惰性GHC中,它直到您请求结果时才完全阻塞。
停止了逆时针转动

2
haskell很酷。
blabla999

12

短暂聊天

这将创建在飞行的新方法,其
  产生的飞行,这一个新的方法
    创建上飞的新方法,它
      ...
    ...
  ..
然后转移到它。

通过创建越来越长的方法名称和大量的接收者,同时强调堆栈内存和堆内存,这又增加了一点点趣味……(但是递归首先打击了我们)。

在Integer中编译:

downTheRabbitHole
    |name deeperName nextLevel|

    nextLevel := self * 2.
    name := thisContext selector.
    deeperName := (name , '_') asSymbol.
    Class withoutUpdatingChangesDo:[
        nextLevel class 
            compile:deeperName , (thisContext method source copyFrom:name size+1).
    ].
    Transcript show:self; showCR:' - and down the rabbit hole...'.
    "/ self halt. "/ enable for debugging
    nextLevel perform:deeperName.

然后通过评估"2 downTheRabbitHole"…… 跳转
……一段时间之后,您将进入调试器,显示RecursionException。

然后,您必须清理所有混乱(SmallInteger和LargeInteger现在都具有大量的仙境代码):

{SmallInteger . LargeInteger } do:[:eachInfectedClass |
    (eachInfectedClass methodDictionary keys 
        select:[:nm| nm startsWith:'downTheRabbitHole_'])
            do:[:each| eachInfectedClass removeSelector:each]

否则花一些时间在浏览器中,删除爱丽丝的仙境。

这是跟踪的开头:

2 - and down the rabbit hole...
4 - and down the rabbit hole...
8 - and down the rabbit hole...
16 - and down the rabbit hole...
[...]
576460752303423488 - and down the rabbit hole...
1152921504606846976 - and down the rabbit hole...
2305843009213693952 - and down the rabbit hole...
[...]
1267650600228229401496703205376 - and down the rabbit hole...
2535301200456458802993406410752 - and down the rabbit hole...
5070602400912917605986812821504 - and down the rabbit hole...
[...]
162259276829213363391578010288128 - and down the rabbit hole...
324518553658426726783156020576256 - and down the rabbit hole...
[...]
and so on...

PS:添加了“ withoutUpdatingChangesFile:”,以避免以后必须清除Smalltalk的永久更改日志文件。

PPS:感谢挑战:思考新事物和创新很有趣!

PPPS:我想指出,一些Smalltalk方言/版本将溢出的堆栈帧复制到堆中-因此它们可能会遇到内存不足的情况。


2
大声笑+1纯粹形式的黑魔法
masterX244

如果有时间,我可以通过使用匿名类的匿名方法来“改进”,以制造有史以来最黑暗的兔子洞……
blabla999 2014年

12

C#

真的很大struct,没有递归,纯C#,不是不安全的代码。

public struct Wyern
{
    double a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
public struct Godzilla
{
    Wyern a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
public struct Cyclops
{
    Godzilla a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
public struct Titan
{
    Cyclops a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;
}
class Program
{
    static void Main(string[] args)
    {
        // An unhandled exception of type 'System.StackOverflowException' occurred in ConsoleApplication1.exe
        var A=new Titan();
        // 26×26×26×26×8 = 3655808 bytes            
        Console.WriteLine("Size={0}", Marshal.SizeOf(A));
    }
}

作为踢手,它使调试窗口崩溃,指出 {Cannot evaluate expression because the current thread is in a stack overflow state.}


和通用版本(感谢NPSF3000的建议)

public struct Wyern<T>
    where T: struct
{
    T a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z;        
}


class Program
{
    static void Main(string[] args)
    {
        // An unhandled exception of type 'System.StackOverflowException' occurred in ConsoleApplication1.exe
        var A=new Wyern<Wyern<Wyern<Wyern<int>>>>();
    }
}

需要更多的通用代码方法:P
NPSF3000

它看起来像递归,但是可以使用嵌套类型参数。
2014年

1
在我发布我的消息之前,没有看到您的C#结构答案。我仍然有一些不同的方法,所以也许我们让它们共存。
Thomas Weller 2014年

11

C#

覆盖==运算符的错误实现:

public class MyClass
{
    public int A { get; set; }

    public static bool operator ==(MyClass obj1, MyClass obj2)
    {
        if (obj1 == null)
        {
            return obj2 == null;
        }
        else
        {
            return obj1.Equals(obj2);
        }
    }

    public static bool operator !=(MyClass obj1, MyClass obj2)
    {
        return !(obj1 == obj2);
    }

    public override bool Equals(object obj)
    {
        MyClass other = obj as MyClass;
        if (other == null)
        {
            return false;
        }
        else
        {
            return A == other.A;
        }
    }
}

可能有人会说operator==使用==操作符进行调用很明显,但是您通常不这么认为==,因此很容易陷入陷阱。


11

使用SnakeYAML开始回复

class A
{

    public static void main(String[] a)
    {
         new org.yaml.snakeyaml.Yaml().dump(new java.awt.Point());
    }
}

编辑:取消高尔夫

读者自行决定:P的工作原理(提示:stackoverflow.com)

顺便说一句:递归是由SnakeYAML动态进行的(您会知道,如果您知道它如何检测到它序列化的字段,然后在Point的源代码中查看)

编辑:告诉一个人如何工作:

SnakeYAML查找一个双getXXXsetXXXmthod具有相同名称为XXX并返回吸气剂的类型是相同的设定器的参数; 令人惊讶的是,Point该类具有Point getLocation()void setLocation(Point P)并返回自身;SnakeYAML不会注意到它,而是在该怪癖和StackOverflows上重复进行。在与他们一起在a内HashMap并在其上询问stackoverflow.com 时发现了那个。


10

C#

错误实现的属性获取器

class C
{
   public int P { get { return P; } }
}

static void Main()
{
   int p = new C().P;
}

14
恕我直言。这是一个明显的递归的经典示例...(因此无效)
Ole Albers 2014年

2
好吧,只有当您完成一次并发现C#吸气剂无法像您认为的那样工作时,这才很明显。毕竟,此代码是成员变量声明,所以为什么不创建实际的成员变量呢?
meustrus

2
这是不比做的一个令人费解的方式更static void Main() { Main(); }
Jodrell

5
@Jodrell您不会Main()意外编写递归。但是,很容易意外地编写一个递归属性,然后被堆栈溢出所迷惑。
svick

1
这对于使用C#的人很有用。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.