Qual é o código mais curto para causar um estouro de pilha? [fechadas]

160

Para comemorar o lançamento público do Stack Overflow, qual é o código mais curto para causar um estouro de pilha? Qualquer idioma é bem-vindo.

ETA: Só para esclarecer essa questão, já que sou um usuário ocasional do Scheme: "recursão" de chamada de cauda é realmente iteração, e qualquer solução que possa ser convertida em uma solução iterativa relativamente trivialmente por um compilador decente não será ser contado. :-P

ETA2: Eu selecionei agora a “melhor resposta”; veja este post para justificativa. Obrigado a todos que contribuíram! :-)

Chris Jester-Young
fonte

Respostas:

212

Todas essas respostas e nenhum Befunge? Eu apostaria uma quantia justa, é a solução mais curta de todas:

1

Não está brincando. Experimente você mesmo: http://www.quirkster.com/iano/js/befunge.html

Edição: Eu acho que preciso explicar este. O operando 1 coloca um 1 na pilha interna do Befunge e a falta de qualquer outra coisa o coloca em um loop sob as regras da linguagem.

Usando o intérprete fornecido, você eventualmente - e eu quero dizer, eventualmente - atinge um ponto em que a matriz Javascript que representa a pilha Befunge se torna muito grande para o realocador do navegador. Se você tivesse um intérprete Befunge simples com uma pilha menor e limitada - como é o caso da maioria dos idiomas abaixo -, esse programa causaria um estouro mais perceptível mais rapidamente.

Patrick
fonte
8
Hmm… mas isso é realmente um estouro de pilha ou apenas um loop infinito? Meu intérprete JS não transbordou, apenas saiu de férias, por assim dizer.
Konrad Rudolph
3
Não é um loop infinito, porque a instrução 1 coloca um 1 na pilha. Eventualmente, seu intérprete Befunge ficará sem espaço de pilha, mas levará um tempo. :)
Patrick
18
Você .. travou meu navegador e .. enviou meu ventilador da CPU para overdrive.
1515 Sam152
2
Surpreendente! Meu computador ou navegador (Opera) não
travou
28
Aqui está um programa Befunge que transborda mais rápido: " Carrega 79 cópias do número 32 a cada duas vezes que envolve em torno de, em vez de 2 cópias do número 1.
KirarinSnow
291

Leia esta linha e faça o que diz duas vezes .

jrudolph
fonte
174

Você também pode tentar isso em c # .net

throw new StackOverflowException();
GateKiller
fonte
29
O pedante em mim diz que não causa o estouro de nenhuma pilha, apenas gera uma exceção. É como dizer que a maneira mais rápida de ser atacado por tubarões é ficar no mar e gritar "Ataque de tubarão!". Apesar disso, vou votar novamente. :)
Bernard
Bem - há alguma diferença? Você pode pegá-lo e continuar? Ou é exatamente como um stackoverflow em c #? Nesse caso, de alguma forma, é um stackoverflow, uma vez que é indistinguível de um ... No entanto - upvote por todas as razões acima
Mo.
18
Se uma pilha transborda na floresta sem ninguém por perto para capturar, isso gera uma exceção?
Eu não diria o 'mais curto', já que não é como se você pudesse compilar uma linha como essa. Ele faz jogar um estouro de pilha rapidamente embora eu acho.
Dominic K
159

Nemerle :

Isso trava o compilador com uma StackOverflowException:

def o(){[o()]}
Cody Brocious
fonte
119

Meu melhor atual (na montagem x86) é:

push eax
jmp short $-1

o que resulta em 3 bytes de código do objeto ( 50 EB FD). Para código de 16 bits, isso também é possível:

call $

o que também resulta em 3 bytes ( E8 FD FF).

Chris Jester-Young
fonte
6
Contar os bytes após a "compilação" (ou montagem) não é código-golfe.
Louis Brandy
37
A pergunta diz "[...] qual é o código mais curto para causar um estouro de pilha?" Ele não especifica código fonte, código interpretado, código de máquina, código de objeto ou código gerenciado ...
Anders Sandvig 15/09/08
Para constar, o servidor de golfe de Shin permite que você envie o código do objeto a ser julgado, embora também conte todos os seus cabeçalhos ELF. Hum ...
Chris Jester-Young
Veja, por exemplo, golf.shinh.org/p.rb?FizzBuzz#x86 para obter alguns exemplos disso. (Sinceramente, não sei como as pessoas podem fazer binários ELF de 99 bytes.) :-P
Chris Jester-Young
7
@ lbrandy: Existem pessoas suficientes que podem escrever código de objeto diretamente. Não posso fazer isso para x86, mas para um certo microprocessador, posso. Eu contaria esse código.
Joey3
113

PIC18

A resposta PIC18 dada por TK resulta nas seguintes instruções (binárias):

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

No entanto, CALL sozinho executará um estouro de pilha:

CALL $
1110 1100 0000 0000
0000 0000 0000 0000

PIC18 menor e mais rápido

Mas o RCALL (chamada relativa) ainda é menor (não a memória global, portanto, não há necessidade de 2 bytes extras):

RCALL $
1101 1000 0000 0000

Portanto, o menor do PIC18 é uma única instrução, 16 bits (dois bytes). Isso levaria 2 ciclos de instrução por loop. Em 4 ciclos de relógio por ciclo de instrução, você tem 8 ciclos de relógio. O PIC18 possui uma pilha de 31 níveis, portanto, após o 32º loop, ela excederá a pilha, em 256 ciclos de clock. Em 64MHz, você sobrecarregaria a pilha em 4 microssegundos e 2 bytes .

PIC16F5x (ainda menor e mais rápido)

No entanto, a série PIC16F5x usa instruções de 12 bits:

CALL $
1001 0000 0000

Novamente, dois ciclos de instrução por loop, 4 relógios por instrução e 8 ciclos de clock por loop.

No entanto, o PIC16F5x possui uma pilha de dois níveis; portanto, no terceiro loop, ela excederá em 24 instruções. A 20MHz, ele transbordaria em 1,2 microssegundos e 1,5 bytes .

Intel 4004

O Intel 4004 possui uma instrução de sub-rotina de chamada de 8 bits:

CALL $
0101 0000

Para os curiosos que correspondem a um ascii 'P'. Com uma pilha de 3 níveis que leva 24 ciclos de relógio para um total de 32,4 microssegundos e um byte . (A menos que você faça um overclock no seu 4004 - vamos lá, você sabe que deseja).

Que é tão pequeno quanto a resposta do befunge, mas muito, muito mais rápido que o código do befunge executado nos intérpretes atuais.

Adam Davis
fonte
77

C #:

public int Foo { get { return Foo; } }
aku
fonte
57

Estouro de buzina!

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

Toda tarefa precisa da ferramenta certa. Conheça a linguagem SO Overflow , otimizada para produzir estouros de pilha:

so
Konrad Rudolph
fonte
7
Se você está criando um idioma especializado para gerar estouros com um mínimo de código, obviamente você deseja (1) entrada vazia produz código transbordante de pilha (provavelmente um pequeno binário que executa o código nativo gerado a partir da entrada do código de montagem) ou (2) ) todos os programas de entrada produzem o referido binário.
Jared Updike
Hmmm, não Turing completo. Eu não sei se você poderia chamá-lo de uma linguagem apenas ainda ...
Adam Davis
42

TeX:

\def~{~.}~

Resulta em:

! Capacidade de TeX excedida, desculpe [tamanho da pilha de entrada = 5000].
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
...
<*> \ def ~ {~.} ~

Látex:

\end\end

Resulta em:

! Capacidade de TeX excedida, desculpe [tamanho da pilha de entrada = 5000].
\ end # 1 -> \ csname end # 1
                      \ endcsname \ @checkend {# 1} \ expandafter \ endgroup \ if @ e ...
<*> \ end \ end
Pi.
fonte
Como ~está ativo, pode ser usado no lugar de \a. E eu descobri o código LaTeX completamente por acidente. :)
Josh Lee
35

Montador Z-80 - no local da memória 0x0000:

rst 00

um byte - 0xC7 - loop infinito de empurrar o PC atual para a pilha e pular para o endereço 0x0000.

Dennis Munsie
fonte
2
Lembro-me de que um eprom em branco seria todo o 0xffs, que são as primeiras 7 (= chamadas 0x0038) instruções. Isso seria útil para depurar seu hardware com um osciloscópio. O barramento de endereço percorreria o espaço de 64K quando a pilha estourou repetidamente, intercalada com leituras de 0xff a partir de 0x0038.
23815 Bill Forster
29

Em inglês:

recursion = n. See recursion.
Vinko Vrsalovic
fonte
32
Qualquer cérebro humano sensível aperfeiçoará a interpretação deste também, e não explodirá. :-P
Chris Jester-Young
73
Chris, cérebros humanos sensíveis estão se tornando uma raridade nos dias de hoje.
Jason Z
20
raridade ... você quer dizer que eles existem?
Adam Lerman
11
Recursão do Google
CodeFusionMobile 3/11/2009
29

Outro exemplo de PHP:

<?
require(__FILE__);
disq
fonte
4
Você pode até receber um curto-circuito pulando o parêntese (mas incluindo o espaço no lugar do primeiro).
alex
26

Que tal o seguinte no BASIC:

10 GOSUB 10

(Eu não tenho um intérprete BASIC, receio, então isso é um palpite).

stusmith
fonte
3
Não é realmente um estouro de pilha, uma vez que o BASIC é uma linguagem sem pilha. Mesmo o VB (que tem uma pilha) não transborda, pois está apenas pulando, não criando um quadro de pilha.
Daniel Spiewak
21
Isso é um GOSUB, não um GOTO. Como RETURNé de onde foi chamado, certamente está usando uma pilha?
Tom
3
Sim, eu concordo. Eu tive muitos estouros de pilha no BASIC nos anos 80.
nickd 16/09/08
6
Eu executei este em yabasic apenas por diversão, e quase derrubou meu computador. Graças a Deus, malloc acabou falhando, mas eu estava paginando como se não houvesse amanhã.
Adam Rosenfield
2
Opa, desculpe, Adam ... me lembra um momento em que alguém acidentalmente escreveu um programa que bifurcava-se recursivamente: derrubou todo um servidor Silicon Graphics.
stusmith
26

Eu amei as respostas de Cody, então aqui está minha contribuição semelhante, em C ++:

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

typedef Overflow<0>::type Kaboom;

Não é uma entrada de código de golfe, por qualquer meio, mas ainda assim, qualquer coisa para um estouro de meta stack! :-P

Chris Jester-Young
fonte
21

Aqui está a minha contribuição C, com 18 caracteres:

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

É muito mais difícil otimizar a chamada final! :-P

Chris Jester-Young
fonte
4
Não compila para mim: "referência indefinida para` main '": P
Andrew Johnson
1
Eu não entendo: por que chamar o () 2x?
Dinah
3
@Dinah: Uma das restrições do meu concurso foi que a otimização da chamada de cauda não conta como recursão; é apenas um loop iterativo. Se você escreveu o () apenas uma vez, isso pode ser otimizado para algo como isto (por um compilador competente): "o: jmp o". Com 2 chamadas de o, o compilador deve usar algo como: "o: call o; jmp o". É a instrução "chamada" recursiva que faz a pilha exceder.
Chris Jester-Young
Você está correto - eu não prestei atenção a essa parte. Obrigado pelo esclarecimento.
Dinah
19

Usando o arquivo em lotes de uma janela chamado "s.bat":

call s
Jude Allred
fonte
17

Javascript

Para aparar mais alguns caracteres e ser expulso de mais lojas de software, vamos com:

eval(i='eval(i)');
Travis Wilson
fonte
15

Groovy:

main()

$ groovy stack.groovy:

Caught: java.lang.StackOverflowError
    at stack.main(stack.groovy)
    at stack.run(stack.groovy:1)
 ...
Chris Broadfoot
fonte
Votou porque é bem interessante. No entanto, expõe uma fraqueza bastante irritante no compilador Groovy (essas chamadas finais podem ser incorporadas em tempo de compilação).
Daniel Spiewak 16/09/08
tem certeza de que é uma chamada de cauda? que cair do final do programa não invoca o shell do intérprete?
Aaron
15

Por favor, diga-me o que significa o acrônimo " GNU ".

Greg
fonte
4
Ou Eine (Eine não é Emacs) ou Zwei (Zwei era Eine inicialmente). :-P
Chris Jester-Young
Ou YAML, ou WINE, ou XNA, ou qualquer um dos outros itens
TM.
Drei (Drei é realmente Emacs Incognito), Fier (Fier é Emacs Reinvented) - ok, então eu só fez aqueles até :-)
Ferruccio
14
Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky);

Aqui está esperando por nenhuma recursão da cauda!

Ryan Fox
fonte
1
Hehe, engraçado. Em relação às conversas, a ideia do "efeito da câmara de eco" também é bastante interessante. Não é bastante indutor de excesso de pilha, mas ainda assim.
Chris Jester-Young
8
Isso não seria uma exceção de ponteiro nulo? Desculpe, eu sei que é uma piada.
jamesh
12

C - Não é o mais curto, mas é livre de recursão. Também não é portátil: trava no Solaris, mas algumas implementações alloca () podem retornar um erro aqui (ou chamar malloc ()). A chamada para printf () é necessária.

#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;
}
bk1e
fonte
Você também pode fazer "ulimit -s16" para definir a pilha muito pequena. Qualquer menor que 16 e o ​​programa nem roda (argumentos insuficientes, aparentemente!).
Andrew Johnson
11

perl em 12 caracteres:

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

bash em 10 caracteres (o espaço na função é importante):

i(){ i;};i
asksol
fonte
11

Python :

so=lambda:so();so()

Alternativamente:

def so():so()
so()

E se o Python otimizou as chamadas de cauda ...:

o=lambda:map(o,o());o()
Cody Brocious
fonte
Para sua sorte, o Python não faz otimização de chamada de cauda; caso contrário, seria desqualificado como duas outras respostas até agora. :-P
Chris Jester-Young
10

Estou selecionando a "melhor resposta" após este post. Mas primeiro, gostaria de reconhecer algumas contribuições muito originais:

  1. os de aku. Cada um explora uma maneira nova e original de causar estouro de pilha. A idéia de fazer f (x) ⇒ f (f (x)) é uma que explorarei na minha próxima entrada, abaixo. :-)
  2. O de Cody que deu ao compilador Nemerle um estouro de pilha.
  3. E (um pouco de má vontade), o do GateKiller é sobre lançar uma exceção de estouro de pilha. :-P

Por mais que eu goste do exposto acima, o desafio é fazer golfe com códigos e, para ser justo com os entrevistados, tenho que conceder a "melhor resposta" ao código mais curto, que é a entrada do Befunge; Eu não acredito que alguém será capaz de superar isso (embora Konrad certamente tenha tentado), então parabéns Patrick!

Vendo o grande número de soluções de pilha a transbordar por recursão, estou surpreso que ninguém (até o momento da redação atual) tenha apresentado o combinador Y (veja o ensaio de Dick Gabriel, O porquê de Y , para uma cartilha). Eu tenho uma solução recursiva que usa o combinador Y, bem como a abordagem f (f (x)) de aku. :-)

((Y (lambda (f) (lambda (x) (f (f x))))) #f)
Chris Jester-Young
fonte
8

Aqui está outro interessante do Scheme:

((lambda (x) (xx)) (lambda (x) (xx)))
Adam Rosenfield
fonte
Muito bom, e também há uma boa simetria. Além disso, usar a formulação (lambda (x) (xx)): ((Y (lambda (x) (xx)))) #f) também é muito divertido!
Chris Jester-Young
Oh, isso é bonito. Também funciona em Ruby, embora não seja tão bonito quanto em Scheme: lambda {| x | x.call x} .call lambda {| x | x.call x}
Wayne Conrad
7

Java

Versão ligeiramente mais curta da solução Java.

class X{public static void main(String[]a){main(a);}}
Misha
fonte
5
Ou (mesmo número de caracteres): public static void main (String ... a) {main ();}
Michael Myers
Ou para os caras TDD (mesmo número de caracteres): public class ${@org.junit.Test $ public void () {$ ();}}
mhaller
Ainda não é o que mais curto (ver minha resposta)
Draemon
6
xor esp, esp
ret
a1k0n
fonte
isso não é realmente um estouro de pilha, mas também é bom: D
botismarius 15/09/08
5

3 bytes:

label:
  pusha
  jmp label

Atualizar

De acordo com a documentação (antiga?) Intel (?) , Também são 3 bytes:

label:
  call label

Anders Sandvig
fonte
São 3 bytes no modo de 32 bits. Boa resposta, considerando que preencherá a pilha muito mais rápido que a minha resposta!
Chris Jester-Young
De acordo com penguin.cz/~literakl/intel/j.html#JMP , jmp é de 3 bytes com endereço de destino relativo de 8, 16 ou 32 bits. O pusha é também 1 bytes, o que perfaz um total de 4
Anders Sandvig
Existem três tipos de jmp, curto, próximo e distante. Jmp curto (usando 0xEB opcode) é de dois bytes. O destino deve estar entre -128 e 127 bytes da próxima instrução. :-)
Chris Jester-Young
Talvez você esteja certo. Estou com preguiça de desenterrar o meu montador e verificar ...;)
Anders Sandvig