Quel est le code le plus court pour provoquer un débordement de pile? [fermé]


160

Pour commémorer le lancement public de Stack Overflow, quel est le code le plus court pour provoquer un débordement de pile? Toute langue est la bienvenue.

ETA: Juste pour être clair sur cette question, vu que je suis un utilisateur occasionnel de Scheme: la "récursion" de l'appel final est en fait une itération, et toute solution qui peut être convertie en une solution itérative de manière relativement triviale par un compilateur décent ne le sera pas Être compté. :-P

ETA2: J'ai maintenant sélectionné une «meilleure réponse»; voir ce post pour la justification. Merci à tous ceux qui ont contribué! :-)

Réponses:


212

Toutes ces réponses et pas de Befunge? Je parierais pas mal que c'est la solution la plus courte de toutes:

1

Sans blague. Essayez-le vous-même: http://www.quirkster.com/iano/js/befunge.html

EDIT: Je suppose que je dois expliquer celui-ci. L'opérande 1 pousse un 1 sur la pile interne de Befunge et le manque de quoi que ce soit d'autre le met en boucle selon les règles du langage.

En utilisant l'interpréteur fourni, vous finirez par - et je veux dire par la suite - atteindre un point où le tableau Javascript qui représente la pile Befunge devient trop grand pour que le navigateur puisse se réallouer. Si vous aviez un interpréteur Befunge simple avec une pile plus petite et limitée - comme c'est le cas avec la plupart des langages ci-dessous - ce programme provoquerait un débordement plus visible plus rapidement.


8
Hmm… mais est-ce vraiment un débordement de pile ou juste une boucle infinie? Mon interprète JS n'a pas débordé, il est juste parti en vacances, pour ainsi dire.
Konrad Rudolph le

3
Ce n'est pas une boucle infinie, car l'instruction 1 pousse un 1 sur la pile. Finalement, votre interpréteur Befunge manquera d'espace dans la pile, mais cela prendra un certain temps. :)
Patrick

18
Vous… avez planté mon navigateur et… envoyé mon ventilateur de processeur en overdrive.
Sam152

2
Incroyable! Mon ordinateur ou navigateur (Opera) ne s'est pas planté mais les deux processeurs fonctionnaient à 100% et la vitesse du ventilateur était à 3.
Secko

28
Voici un programme Befunge qui déborde plus rapidement: " il charge 79 copies du numéro 32 toutes les deux fois qu'il s'enroule, plutôt que 2 copies du numéro 1.
KirarinSnow

291

Lisez cette ligne et faites ce qu'elle dit deux fois .


174

Vous pouvez également essayer ceci en C # .net

throw new StackOverflowException();

29
Le pédant en moi dit que cela ne provoque aucun débordement de pile, mais lève simplement une exception. C'est comme dire que le moyen le plus rapide d'être attaqué par des requins est de se tenir dans la mer et de crier "Shark attack!". Malgré cela, je voterai à la hausse. :)
Bernard

Eh bien, y a-t-il une différence? Pouvez-vous l'attraper et continuer? Ou est-ce exactement comme un stackoverflow en c #? Dans ce cas, il s'agit en quelque sorte d'un stackoverflow, car il est impossible de le distinguer d'un seul ... Cependant - vote pour toutes les raisons ci
Mo.

18
Si une pile déborde dans les bois sans personne pour attraper, cela lève-t-il une exception?

Je ne dirais pas le `` plus court '' car ce n'est pas comme si vous pouviez compiler un one-liner comme ça. Il fait jeter un débordement de pile rapidement si je suppose.
Dominic K du

159

Nemerle :

Cela plante le compilateur avec une exception StackOverflowException:

def o(){[o()]}

119

Mon meilleur actuel (en assemblage x86) est:

push eax
jmp short $-1

ce qui donne 3 octets de code objet ( 50 EB FD). Pour le code 16 bits, cela est également possible:

call $

ce qui donne également 3 octets ( E8 FD FF).


6
Compter les octets après "compilation" (ou assemblage) n'est pas du code-golf.
Louis Brandy

37
La question dit "[...] quel est le code le plus court pour provoquer un débordement de pile?" Il ne spécifie pas le code source, le code interprété, le code machine, le code objet ou le code managé ...
Anders Sandvig

Pour mémoire, le serveur de golf de Shin vous permet d'envoyer du code objet pour être jugé, bien qu'il comptera également tous vos en-têtes ELF. Hmm ....
Chris Jester-Young

Voir, par exemple, golf.shinh.org/p.rb?FizzBuzz#x86 pour quelques exemples de ceci. (Honnêtement, je ne sais pas comment les gens peuvent créer des binaires ELF de 99 octets.) :-P
Chris Jester-Young

7
@lbrandy: Il y a suffisamment de personnes qui peuvent écrire directement du code objet. Je ne peux pas le faire pour x86 mais pour un certain microprocesseur, je peux. Je compterais ce code.
Joey

113

PIC18

La réponse PIC18 donnée par TK entraîne les instructions suivantes (binaire):

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

Cependant, CALL seul effectuera un débordement de pile:

CALL $
1110 1100 0000 0000
0000 0000 0000 0000

PIC18 plus petit, plus rapide

Mais RCALL (appel relatif) est encore plus petit (pas de mémoire globale, donc pas besoin des 2 octets supplémentaires):

RCALL $
1101 1000 0000 0000

Ainsi, le plus petit sur le PIC18 est une seule instruction, 16 bits (deux octets). Cela prendrait 2 cycles d'instructions par boucle. À 4 cycles d'horloge par cycle d'instruction, vous avez 8 cycles d'horloge. Le PIC18 a une pile de 31 niveaux, donc après la 32ème boucle, il débordera de la pile, en 256 cycles d'horloge. À 64 MHz, vous déborderiez la pile en 4 microsecondes et 2 octets .

PIC16F5x (encore plus petit et plus rapide)

Cependant, la série PIC16F5x utilise des instructions 12 bits:

CALL $
1001 0000 0000

Encore une fois, deux cycles d'instruction par boucle, 4 horloges par instruction donc 8 cycles d'horloge par boucle.

Cependant, le PIC16F5x a une pile à deux niveaux, donc sur la troisième boucle il déborderait, en 24 instructions. À 20 MHz, il déborderait en 1,2 micro seconde et 1,5 octets .

Intel 4004

L' Intel 4004 a une instruction de sous-programme d'appel 8 bits:

CALL $
0101 0000

Pour les curieux qui correspond à un ascii 'P'. Avec une pile à 3 niveaux qui prend 24 cycles d'horloge pour un total de 32,4 micro secondes et un octet . (Sauf si vous overclockez votre 4004 - allez, vous savez que vous voulez.)

Ce qui est aussi petit que la réponse befunge, mais beaucoup, beaucoup plus rapide que le code befunge exécuté dans les interpréteurs actuels.


77

C #:

public int Foo { get { return Foo; } }

57

Hoot trop-plein!

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

55

Chaque tâche a besoin du bon outil. Découvrez le langage SO Overflow , optimisé pour produire des débordements de pile:

so

7
Si vous créez un langage spécialisé pour générer des débordements avec un minimum de code, vous voudrez évidemment (1) une entrée vide produit du code de débordement de pile (probablement un petit binaire qui exécute le code natif généré à partir de l'entrée de code d'assemblage) ou (2 ) tous les programmes d'entrée produisent ledit binaire.
Jared Updike

Hmmm, pas Turing complet. Je ne sais pas si vous pouvez encore appeler cela une langue ...
Adam Davis

42

Texas:

\def~{~.}~

Résulte en:

! Capacité TeX dépassée, désolé [taille de la pile d'entrée = 5000].
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
~ -> ~
    .
...
<*> \ def ~ {~.} ~

Latex:

\end\end

Résulte en:

! Capacité TeX dépassée, désolé [taille de la pile d'entrée = 5000].
\ end # 1 -> \ csname end # 1
                      \ endcsname \ @checkend {# 1} \ expandafter \ endgroup \ if @ e ...
<*> \ end \ end

Comme ~est actif, il peut être utilisé à la place de \a. Et j'ai découvert le code LaTeX complètement par accident. :)
Josh Lee

35

Assembleur Z-80 - à l'emplacement de mémoire 0x0000:

rst 00

un octet - 0xC7 - boucle sans fin de poussée du PC actuel vers la pile et de saut à l'adresse 0x0000.


2
Je me souviens qu'un eprom vierge serait tous les 0xffs qui sont les 7 premières instructions (= appeler 0x0038). Cela serait utile pour déboguer votre matériel avec un oscilloscope. Le bus d'adresses parcourrait l'espace de 64 Ko lorsque la pile débordait à plusieurs reprises, entrecoupée de lectures de 0xff à partir de 0x0038.
Bill Forster


29

Un autre exemple PHP:

<?
require(__FILE__);

4
Vous pourriez même être court-circuité en sautant les parenthèses (mais en incluant un espace à la place du premier).
alex le

26

Que diriez-vous de ce qui suit en BASIC:

10 GOSUB 10

(Je n'ai pas d'interprète BASIC, je crains donc c'est une supposition).


3
Ce n'est pas vraiment un débordement de pile puisque BASIC est un langage sans pile. Même VB (qui a une pile) ne déborderait pas là-dessus car il ne fait que sauter, ne créant pas un cadre de pile.
Daniel Spiewak

21
C'est un GOSUB, pas un GOTO. Puisqu'il RETURNest de là où il a été appelé, il utilise sûrement une pile?
Tom

3
Oui je suis d'accord. J'ai eu de nombreux débordements de pile en BASIC dans les années 80.
nickd le

6
J'ai lancé celui-ci en yabasic juste pour le plaisir, et il a failli détruire mon ordinateur. Dieu merci, malloc a finalement échoué, mais je pageais comme pas de lendemain.
Adam Rosenfield

2
Oups désolé Adam ... me rappelle un moment à l'université où quelqu'un a accidentellement écrit un programme qui se dérobait de manière récursive: il a arrêté un serveur Silicon Graphics entier.
stusmith

26

J'ai adoré les tas de réponses de Cody, alors voici ma contribution similaire, en C ++:

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

typedef Overflow<0>::type Kaboom;

Pas une entrée de code de golf en aucun cas, mais quand même, quoi que ce soit pour un débordement de méta-pile! :-P


21

Voici ma contribution C, pesant 18 caractères:

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

C'est beaucoup plus difficile à optimiser! :-P


4
Ne compile pas pour moi: "référence indéfinie à" main "": P
Andrew Johnson

1
Je ne comprends pas: pourquoi appeler o () 2x?
Dinah

3
@Dinah: L'une des contraintes de mon concours était que l'optimisation des appels de fin ne compte pas comme une récursivité; c'est juste une boucle itérative. Si vous n'avez écrit o () qu'une seule fois, cela peut être optimisé pour les appels finaux en quelque chose comme ceci (par un compilateur compétent): "o: jmp o". Avec 2 appels de o, le compilateur doit utiliser quelque chose comme: "o: call o; jmp o". C'est l'instruction "appel" récursive qui fait déborder la pile.
Chris Jester-Young

Vous avez raison - je n'ai pas fait attention à cette partie. Merci pour la clarification.
Dinah


17

Javascript

Pour couper quelques caractères de plus et nous faire expulser de plus de boutiques de logiciels, allons-y avec:

eval(i='eval(i)');

15

Sensationnel:

main()

$ groovy stack.groovy:

Caught: java.lang.StackOverflowError
    at stack.main(stack.groovy)
    at stack.run(stack.groovy:1)
 ...

Voté parce que c'est assez intéressant. Expose une faiblesse plutôt ennuyeuse dans le compilateur Groovy (de tels appels de queue peuvent être intégrés au moment de la compilation).
Daniel Spiewak

êtes-vous sûr que c'est un appel de queue? que tomber la fin du programme n'invoque pas l'interpréteur shell?
Aaron


14
Person JeffAtwood;
Person JoelSpolsky;
JeffAtwood.TalkTo(JoelSpolsky);

En espérant aucune récursion de queue!


1
Hehe, drôle. En ce qui concerne les conversations, l'idée de «l'effet de chambre d'écho» est également très intéressante. Pas tout à fait induisant un débordement de pile, mais quand même.
Chris Jester-Young

8
Ne serait-ce pas une exception de pointeur nul? Désolé, je sais que c'est une blague.
jamesh

12

C - Ce n'est pas le plus court, mais il est sans récursivité. Ce n'est pas non plus portable: il plante sous Solaris, mais certaines implémentations d'alloca () peuvent renvoyer une erreur ici (ou appeler malloc ()). L'appel à printf () est nécessaire.

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

Vous pouvez aussi simplement faire "ulimit -s16" pour définir la pile vraiment petite. Tout plus petit que 16 environ et le programme ne s'exécute même pas (args apparemment insuffisants!).
Andrew Johnson du

11

perl en 12 caractères:

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

bash en 10 caractères (l'espace dans la fonction est important):

i(){ i;};i

11

essayez de mettre plus de 4 galettes sur un seul hamburger. débordement de pile.


1
Ici, en Nouvelle-Zélande, nous avons Burger Wisconsin, où ils utilisent de grosses mais fines galettes. Je suis sûr que vous pouvez en empiler plus de 4 si vous le souhaitez; ce sera un hamburger très cher cependant!
Chris Jester-Young



11

Python :

so=lambda:so();so()

Alternativement:

def so():so()
so()

Et si Python optimisé tail appelle ...:

o=lambda:map(o,o());o()

Heureusement pour vous, Python ne fait pas d'optimisation des appels de fin; sinon, il serait disqualifié comme deux autres réponses jusqu'à présent. :-P
Chris Jester-Young

10

Je sélectionne la «meilleure réponse» après cet article. Mais tout d'abord, je tiens à remercier quelques contributions très originales:

  1. ceux d'aku. Chacun explore une manière nouvelle et originale de provoquer un débordement de pile. L'idée de faire f (x) ⇒ f (f (x)) est celle que j'explorerai dans ma prochaine entrée, ci-dessous. :-)
  2. Celui de Cody qui a donné au compilateur Nemerle un débordement de pile.
  3. Et (un peu à contrecœur), celle de GateKiller sur le fait de lancer une exception de débordement de pile. :-P

Tout comme j'aime ce qui précède, le défi consiste à faire du golf codé, et pour être juste envers les répondants, je dois attribuer la «meilleure réponse» au code le plus court, qui est l'entrée Befunge; Je ne pense pas que quiconque puisse battre ça (bien que Konrad ait certainement essayé), alors félicitations Patrick!

Voyant le grand nombre de solutions de débordement de pile par récursivité, je suis surpris que personne n'ait (à l'heure actuelle) évoqué le combinateur Y (voir l'essai de Dick Gabriel, The Why of Y , pour une introduction). J'ai une solution récursive qui utilise le combinateur Y, ainsi que l'approche f (f (x)) d'aku. :-)

((Y (lambda (f) (lambda (x) (f (f x))))) #f)

8

En voici un autre intéressant de Scheme:

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

Très joli, et il y a aussi une bonne symétrie. De plus, utiliser la formulation (lambda (x) (xx)): ((Y (lambda (x) (xx))) #f) est également très amusant!
Chris Jester-Young le

Oh, c'est joli. Cela fonctionne aussi dans Ruby, mais pas aussi joli que dans Scheme: lambda {| x | x.call x} .call lambda {| x | x.call x}
Wayne Conrad

7

Java

Version légèrement plus courte de la solution Java.

class X{public static void main(String[]a){main(a);}}

5
Ou (même nombre de caractères): public static void main (String ... a) {main ();}
Michael Myers

Ou pour les types TDD (même nombre de caractères): public class ${@org.junit.Test public void $ () {$ ();}}
mhaller

Toujours pas le plus court (voir ma réponse)
Draemon


5

3 octets:

label:
  pusha
  jmp label

Mettre à jour

D'après la (ancienne?) Documentation Intel (?) , C'est aussi 3 octets:

label:
  call label


C'est 3 octets en mode 32 bits. Bonne réponse, étant donné que cela remplira la pile beaucoup plus rapidement que ma réponse!
Chris Jester-Young

Selon penguin.cz/~literakl/intel/j.html#JMP , jmp est de 3 octets avec une adresse de destination relative de 8, 16 ou 32 bits. Le pusha fait également 1 octet, ce qui fait un total de 4
Anders Sandvig

Il existe trois types de jmp, court, proche et éloigné. Le jmp court (utilisant l'opcode 0xEB) est de deux octets. La destination doit être entre -128 et 127 octets de l'instruction suivante. :-)
Chris Jester-Young

Peut-être que tu as raison. Je suis trop paresseux pour déterrer mon assembleur et vérifier ...;)
Anders Sandvig
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.