Ecrivez un programme qui fonctionne à l'infini et alloue de plus en plus de mémoire sur le segment de mémoire au fur et à mesure de son exécution, du moins jusqu'à atteindre la limite du système d'exploitation quant à la quantité de mémoire pouvant être allouée.
De nombreux noyaux ne réservent pas la mémoire allouée tant que vous ne l'utilisez pas, donc si votre programme est en C ou dans une autre langue de bas niveau, vous devez vous assurer d'écrire quelque chose sur chaque page. Si vous utilisez un langage interprété, vous n'aurez probablement pas à vous inquiéter à ce sujet.
Le code le plus court gagne.
(reduce conj [] (range))
(Clojure) se lève à 737mb, puis cesse juste de grandir. Idk comment ça ne monte pas continuellement. Il "pense" que je veux imprimer toute la liste à la fin, il ne devrait donc rien jeter. Très frustrant.Réponses:
Funge-98 (
cfunge
), 1 octetJ'aurais posté ce message plus tôt, mais j'ai décidé de le tester et il a fallu un certain temps pour que mon ordinateur redevienne utilisable.
cfunge
stocke la pile Funge sur le tas du système d'exploitation (ce qui est facilement vérifiable en exécutant le programme avec une petite limite de mémoire, ce que j'aurais dû faire plus tôt!), donc une pile en croissance continue (comme avec ce programme qui pousse à9
plusieurs reprises; Les programmes Funge renvoyant par défaut de la fin d’une ligne au début allouent de la mémoire pour toujours. Ce programme fonctionne probablement aussi dans certaines implémentations de Befunge-93.Plus intéressant:
C’était ma première idée et c’est une allocation infinie qui ne repose pas sur la pile Funge (bien qu’elle explose également la pile Funge). Pour commencer, la
"
commande pousse une copie du reste du programme dans la pile (il s'agit d'une chaîne et le programme est renvoyé à la ligne, de sorte que la citation proche sert également de citation ouverte). Ensuite, leN
reflet (cela n’a aucune signification par défaut), ce qui entraîne l’exécution du programme en arrière. Le"
lance à nouveau et pousse le programme dans la pile - à l’inverse cette fois-ci, avec leN
haut de la pile - puis le programme tourne autour, chargeant une bibliothèque avec un nom de 4 lettres (4(
; laNULL
bibliothèque fait partie decfunge
la bibliothèque standard de).NULL
définit toutes les lettres majuscules à faire refléter, donc leL
reflète, la#
saute la charge de la bibliothèque sur le chemin du retour, les4
objets indésirables qui nous importent le moins et le programme entier se répète depuis le début. Étant donné que le chargement d'une bibliothèque à plusieurs reprises a un effet et nécessite que la liste de commandes de la bibliothèque soit stockée une fois pour chaque copie de la bibliothèque (ceci est impliqué par la sémantique de Funge-98), la mémoire perd de la mémoire via le stockage non-pile (qui est une sauvegarde). méthode alternative pour définir "tas", par rapport à la langue plutôt qu’au système d’exploitation).la source
0
; il est possible que l'implémentation de Funge ou le système d'exploitation trouve un moyen d'optimiser cette sortie, étant donné que la mémoire en question est déjà pleine de zéros). Je viens de choisir9
arbitrairement.Brainfuck, 5 octets
Cela nécessite un interprète qui ne limite pas la longueur de la bande.
la source
Bash + coreutils, 5
ou
Ruby, 5
yes
produit une sortie sans fin. Mettreyes
en backticks indique au shell de capturer toutes les sorties puis d’exécuter cette sortie en tant que commande. Bash continuera à allouer de la mémoire pour cette chaîne sans fin jusqu'à épuisement du tas. Bien sûr, la sortie résultante serait une commande non valide, mais nous devrions manquer de mémoire avant que cela ne se produise.Merci à @GB d’avoir fait remarquer que c’est aussi un polyglotte en rubis.
la source
Python, 16 octets
Conserve l'imbrication
a
jusqu'à ce qu'une erreur soit atteinte:Les premières itérations (en tuples) ressemblent à ceci:
et ainsi de suite.
la source
> <> (Poisson), 1 octet
Essayez-le ici!
0
peut effectivement être substitué à tout nombre hexadécimal 1-f.Explication
0
in> <> crée simplement une boîte à code 1x1 pour le poisson. Il ajoute constamment un0
sur la pile, nage à droite, ce qui revient en boucle0
, l'ajoutant à nouveau à la pile. Cela durera pour toujours.la source
.
(ou tout caractère non-blanc) pour déplacer le0
dans la ligne d'exécution.0000000...
comme un littéral entier unique, et la chaîne qu’il construit constitue ce qui continue à prendre plus de mémoire. Un programme qui fonctionne comme celui-ci seraita
(pousse 10 infiniment).Java 101 octets
Saisir le programme principal dans une boucle sans fin après avoir créé et jeté un objet. La récupération de place fait des fuites en créant 2 objets pour chaque objet supprimé.
la source
Perl, 12 octets
En perl, l'
x
opérateur, avec une chaîne à gauche et un nombre à droite, génère une chaîne répétée. Alors"abc" x 3
évalue à"abcabcabc"
.L'
x=
opérateur mute l'argument de gauche en remplaçant le contenu de la variable de gauche par le résultat de la répétition de son contenu autant de fois que son côté droit l'indique.Perl a un certain nombre de variables construites avec un nom étrange
$"
, dont l’ une est , dont la valeur initiale est un seul espace.L'
redo
opérateur saute au début de l'enceinte{}
.La première fois que l'
x=
opérateur se fait, il modifie la valeur de$"
de" "
"à" "
qui est 9 places.La deuxième fois que l'
x=
opérateur a terminé, il modifie la valeur de$"
to" "
, qui est de 81 espaces.La troisième fois,
$"
devient une chaîne d'espaces de 729 octets.Je pense que tu sais où ça va aller :).
la source
$_.=7
dans ma boucle, mais je réalisais que si je pouvais l'utiliser, lax=
mémoire s'épuiserait beaucoup plus rapidement, puisperldoc perlvar
je choisirais quelque chose qui conviendrait.{$^O++;redo}
est un octet plus court quand^O
est un seulchr(15)
octet. Bien que cela gaspille BEAUCOUP plus lentement la mémoire - il faut 1 000 000 itérations sous Windows pour perdre un octet. Travaillera sur n'importe quel OS dont le nom commence par une lettre latine.sed, 5 octets
Golfé
Utilisation (toute entrée fera l'affaire)
A expliqué
Capture d'écran
Essayez-le en ligne!
la source
Haskell,
2319 octetsImprimer la somme d'une liste infinie
la source
sum
est défini commefoldl (+) 0
, et qu'est-ce qui empêche l'analyse de la rigueur d'entrer dans l'action, d'empêcher l'explosion de thunk? L'avez-vous exécuté compilé avec des optimisations?sum
ne saura pas à l'avance que la liste est infinie etprint
qu'il faut en évaluer la somme en premier. Et oui, je l'ai compilé avec optimisationsInteger
, les nombres sont illimités et que la mémoire exploitée par le résultat actuel de bignum augmente effectivement.sum xs = foldl (+) 0 xs
peut fonctionner en pile constante, comme le ferait n'importe quelle boucle impérative .foldl' (+) 0 xs
sera certainement. Donc, la seule chose qui alloue de la mémoire avec certitude est le résultat provisoire de bignum.C ++ (utilisant le compilateur g ++),
272315 octetsMerci à Neop de m'aider à supprimer 4 octets
Cette solution ne gaspille pas vraiment de mémoire car elle alloue tout sur la pile et provoque ainsi un débordement de pile. C'est simplement infiniment récursif. Chaque récursivité entraîne l’allocation de mémoire jusqu’à ce que la pile déborde.
Solution alternative
Cette solution manque réellement de mémoire.
Sortie Valgrind
Ceci est la sortie Valgrind après avoir terminé le programme plusieurs secondes après le début du temps d'exécution. Vous pouvez voir qu'il perd certainement de la mémoire.
la source
int
jusqu'à ce que je voie votre message , merci!C++
, juste son dialecte g ++: C ++ interdit d'appeler main; C ++ nécessite uneint main...
déclaration. Mais la solution est toujours soignée :-)main
.JAVA,
817978 octetsJAVA (HotSpot)
7170 octetsPlus court que les autres réponses Java au moment où j'ai posté (81, 79 octets plus tard):
Comme suggéré par @Olivier Grégoire, un octet supplémentaire peut être sauvegardé:
Placer en
x+=x.intern()
tant qu'incrément de boucle for n'aiderait en rien, car un point-virgule est toujours requis pour terminer l'instruction for.Comme suggéré par @ETHproductions, utiliser uniquement les
x+=x
œuvres suivantes:Ce qui peut également bénéficier du conseil de @Olivier Grégoire:
Ma seule inquiétude à ce sujet est qu'il n'est pas garanti d'allouer des données sur le tas , car une JVM efficace peut facilement réaliser qu'elle
x
n'échappe jamais à la fonction locale. L'utilisationintern()
évite ce problème car les chaînes internes finissent par être stockées dans un champ statique. Cependant, HotSpot génère unOutOfMemoryError
pour ce code, donc je suppose que ça va.Mise à jour: @Olivier Gregoire a également souligné que le
x+=x
code peut être utiliséStringIndexOutOfBoundsException
plutôt queOOM
lorsque beaucoup de mémoire est disponible. En effet, Java utilise le type 32 bitsint
pour indexer des tableaux (et les chaînes ne sont que des tableaux dechar
). Cela n'affecte pas lax+=x.intern()
solution car la mémoire requise pour cette dernière est quadratique dans la longueur de la chaîne et doit donc être mise à l'échelle jusqu'à l'ordre de 2 ^ 62 octets alloués.la source
x+=x;
?x+=x.intern()
derrière le dernier point-virgule de la boucle forintern
mais j'étais plutôt heureux avec Unsafe et, finalement, j'ai cessé de chercher, haha. A l'origine, cette question spécifiait "fuite de mémoire", raison pour laquelle je n'ai pas fait simplement une réponse concat.# Java (HotSpot), 71 bytes
). De cette façon, vous n'avez pas à vous soucier de la solution potentiellement tricheuse; Les programmes spécifiques aux implémentations sont courants non seulement dans le golf, mais également dans le monde plus vaste de la programmation. Aussi longtemps que vous savez ce que vous faites, cela peut parfois être plus approprié qu'un programme portable, par exemple hors script.x+=x;
n'épuise pas la mémoire entière. Avec 64 Go, je reçois unStringIndexOutOfBoundsException
, pas un MOO. Avec.intern()
je reçois toujours le MOO.Perl 6 , 13 octets
Explication:
@ =
stocker le résultat dans un tableau sans nomeager
rendre avide la liste suivante0 .. *
plage infinie commençant à zérola source
///, 7 octets
Remplacez constamment
a
paraa
, ad nauseum.la source
aad naauseum
ad nauseam
=>aad naauseaam
//a/
? Cela semble remplacer pour toujours `` (rien) para
, mais je ne sais pas si cela est spécifié exactement.Python 3, 16 octets
Cela vient du fait qu'il n'y a pas de limite à la taille entière dans Python 3; à la place, les entiers peuvent occuper autant de mémoire que le système peut en gérer (si quelque chose me semble mal à propos, corrigez-moi).
la source
Rouille, 46 octets
Vous remarquez quelque chose d’intéressant à propos de ce programme Rust, des fuites d’allocations de tas jusqu’à épuisement de mémoire?
C'est vrai, pas de blocage dangereux. Rust garantit la sécurité de la mémoire en code sécurisé (pas de lecture des données non initialisées, lecture après free, double free, etc.), mais les fuites de mémoire sont considérées comme parfaitement sûres. Il existe même une fonction explicite permettant au compilateur d'oublier le nettoyage RAII des variables hors de portée, que j'utilise ici.
la source
TI-83 Hex Assembly, 7 octets
Crée des apparitions indéfiniment jusqu’à ce que
ERR:MEMORY
le système d’exploitation l’ envoie . Courez avecAsm(prgmM)
. Je compte chaque paire de chiffres hexadécimaux comme un octet.la source
Python, 8 octets
Le PO a permis la technicité d’un programme qui n’exécute pas techniquement "pour toujours", mais alloue plus de mémoire que n’importe quel ordinateur. Ce n'est pas tout à fait un googolplex (ce serait
10**10**100
11 octets), mais naïvement, enregistrez la base 2 du nombre estc'est-à-dire 10 ^ 94 bits pour le représenter. WolframAlpha estime que cette taille est supérieure de 10 ^ 76 à celle du Web profond (notez qu’il ya environ 10 ^ 80 atomes dans l’univers ).
Pourquoi 2 au lieu de 9 demandez-vous? Cela ne fait pas beaucoup de différence (utiliser 9 ne ferait qu'augmenter le nombre de bits d'un facteur de
log2(9) = 3.2
, ce qui ne change même pas l'exposant). Par contre, le programme est beaucoup plus rapide avec 2 car le calcul est plus simple. Cela signifie qu’elle remplit immédiatement la mémoire, contrairement à la version 9, qui prend un peu plus de temps en raison des calculs requis. Pas nécessaire, mais bien si vous voulez "tester" cela (ce que j'ai fait).la source
Gelée ,
32 octets-1 octet grâce à Dennis (
W
wraps)Un lien (c'est-à-dire une fonction ou une méthode), qui fonctionne également comme un programme complet, qui encapsule de manière récursive ses entrées dans une liste.
L'entrée commence à zéro de sorte que le premier passage crée la liste.
[0]
Le second passage le fait ensuite.
[[0]]
Le troisième passage le fait ensuite
[[[0]]]
et ainsi de suite ...
Précédent 3 byter, qui fuit beaucoup plus rapidement:
concatène de manière récursive toutes les sous-listes contiguës non vides de son entrée en son entrée.
[0]
->[0,[0]]
->[0,[0],[0],[[0]],[0,[0]]]
et ainsi de suite ...la source
‘ß
devrait être beaucoup.Wß
devrait quand même faire l'affaire.Java 7, 106 octets
Moins de golf
La
finalize
méthode est appelée sur un objet par le récupérateur de place lorsque cette dernière détermine qu'il n'y a plus de références à l'objet. J'ai simplement redéfini cette méthode en boucle pour que le ramasse-miettes ne libère jamais la mémoire. Dans lamain
boucle, je crée de nouveaux objets qui ne seront jamais nettoyés et qui finiront par utiliser toute la mémoire disponible.Java 7 (alternative ludique), 216 octets
Moins de golf
C'est un amusement plus que toute autre chose. Cette réponse utilise la
Unsafe
bibliothèque Sun, qui est une API interne non documentée. Vous devrez peut-être modifier les paramètres de votre compilateur pour autoriser les API restreintes.Unsafe.allocateMemory
alloue un nombre spécifié d'octets (sans vérification de limite) qui ne se trouve ni sur le tas, ni dans la gestion du récupérateur de mémoire java, de sorte que cette mémoire reste en place jusqu'à ce que vous appeliezUnsafe.freeMemory
ou que le volume de mémoire jvm soit saturé.la source
Haskell, 24 octets
Le problème principal à Haskell est de vaincre la paresse.
main
doit avoir un certainIO
type, donc simplement appelermain=f 9
ne fonctionnerait pas. Utilisermain=pure(f 9)
soulève le type def 9
à unIO
type. Cependant, en utilisant des constructions commemain=pure 9
ne fait rien, le9
est retourné ou affiché nulle part, mais simplement jeté, il n’est donc pas nécessaire d’évaluer l’argument depure
, doncmain=pure(f 9)
aucune mémoire ne sera allouée car ellef
n’est pas appelée. Pour appliquer l'évaluation, l'$!
opérateur existe. Il applique simplement une fonction à un argument mais évalue d'abord l'argument. Donc, utilisermain=pure$!f 9
évaluef
et alloue donc continuellement plus de mémoire.la source
f x=f x
œuvres aussi, non? (-2 octets)f x=f x
produit une boucle infinie, mais sans allouer de nouvelle mémoire.f!x=x*f(x*x)
devrait le rendre résistant aux optimisations.dc, 7 octets
[ddx]
pousse une chaîne contenant "ddx" dans la pile.dx
le duplique puis l'exécute en tant que code (en laissant une copie sur la pile). Lorsqu'il est exécuté, il fait deux doublons puis en exécute un, laissant un exemplaire de plus sur la pile à chaque fois.la source
Haskell (utilisant ghc 8.0.1), 11 octets
Récursion sans queue.
main
s’appelle et puis à nouveau.la source
Stack space overflow: current size 33624 bytes.
33 Ko, ce qui semble assez faible, contrairement à la mémoire totale de 6 G signalée par le système d'exploitation.C (linux), 23 octets
sbrk()
incrémente le haut du segment de données du nombre d'octets donné, augmentant ainsi effectivement la quantité de mémoire allouée au programme - du moins comme indiqué dans leVIRT
champ detop
sortie. Cela ne fonctionne que sous Linux - l'implémentation de macOS est apparemment une émulation qui n'autorise que l'allocation d'un maximum de 4 Mo.Donc, une réponse légèrement plus générale:
C, 25 octets
Je l'ai regardé sur le moniteur d'activité macOS. Il est allé jusqu'à environ 48 Go, puis le processus a finalement reçu un signal SIGKILL. FWIW mon macbook pro a 16 Go. La plupart de la mémoire utilisée a été signalée comme étant compressée.
Notez que la question nécessite effectivement l'écriture de chaque attribution, ce qui ne se produit pas explicitement ici. Cependant, il est important de noter que pour chaque
malloc(9)
appel, ce ne sont pas seulement les 9 octets demandés par l'utilisateur qui sont alloués. Pour chaque bloc alloué, il y aura un en-tête malloc qui sera également alloué quelque part sur le tas, sur lequel les élémentsmalloc()
internes écrivent nécessairement .la source
malloc()
bloc ed doit toujours avoir son propre espace alloué réel. Cela fonctionne sur macOS et Ubuntu.main(){main(malloc(9));}
, mais pour ne pas empiler le débordement, il faut optimiser l'optimisation de l'appel final, et gcc ne semble pas vouloir le faire surmain
...Perl, 4 octets
S'exécute, dans l'interprète en cours. Une fois l'opération terminée, l'exécution retourne au script d'appel, qui nécessite une pile d'appels.
la source
Raquette, 13 octets
Je ne suis pas tout à fait sûr si ma réponse tombe sous cette question. S'il vous plaît laissez-moi savoir si je devrais supprimer cette réponse.
la source
l
comme une fonction qui fait la récursion sans appel en arrière. Je dirais que ça compte.JavaScript
2221171615 octetsSauvegardé 4 octets en encapsulant la liste dans une autre liste, comme dans la réponse @ Jonathan de Jelly Allan.
Enregistré 1 octet grâce à @ETHProductions
Solution alternative 15 octets (fonctionne uniquement avec les appels finaux appropriés)
la source
f=_=>f();f()
? 12 octetsa=0
. La première itération aboutiraita=[undefined]
Ruby, 11 octets
Conserve de poussée
9
sur$*
, qui est un tableau contenant initialement les arguments de ligne de commande pour le processus Ruby.la source
05AB1E , 2 octets
Essayez-le en ligne! Continuons simplement à pousser
abcdefghijklmnopqrstuvwyxz
sur la pile pour l'éternité.Toutes les solutions possibles à 2 octets:
la source
Python, 35 octets
a
est jamais libéré et ne fait que grossir jusqu'à ce que vous frappez unMemoryError
Vous pouvez voir l'exécution sur Python Tutor .
la source
a+=a,
?TI-BASIC, 8
(tous les jetons de 1 octet et deux nouvelles lignes)
Cela fuit continuellement la mémoire car un flux de contrôle structuré, tel que la
While
fermeture anticipée prévue par unEnd
élément, presse quelque chose sur la pile (pas la pile du système d'exploitation, une pile séparée dans la mémoire heap) pour en garder la trace. Mais ici, nous utilisonsGoto
pour quitter la boucle (donc noEnd
est exécuté pour retirer la chose de la pile), on laWhile
voit à nouveau, la chose est poussée à nouveau, etc. Donc, elle continue de les pousser jusqu'à ce que vous obteniezERR:MEMORY
la source