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! :-)

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.


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


174

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

throw new StackOverflowException();

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()]}

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).


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.


77

C #:

public int Foo { get { return Foo; } }

57

Estouro de buzina!

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

55

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

so

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

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.


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

Outro exemplo de PHP:

<?
require(__FILE__);

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).


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


21

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

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

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


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


17

Javascript

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

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)
 ...

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 ".


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!


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

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

11

tente colocar mais de 4 hambúrgueres em um único hambúrguer. estouro de pilha.


1
Aqui na Nova Zelândia, temos o Burger Wisconsin, onde eles usam hambúrgueres grandes mas finos. Tenho certeza de que você pode empilhar mais de 4 delas, se quiser; será um hambúrguer muito caro!
Chris Jester-Young



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()

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)

8

Aqui está outro interessante do Scheme:

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

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

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


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


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
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.