Programme le plus court qui alloue de la mémoire en permanence

49

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.

tbodt
la source
13
Un débordement de pile est-il une solution valable? La mémoire doit-elle être divulguée ou simplement allouée?
Wheat Wizard,
1
@WheatWizard La mémoire ne doit pas nécessairement être perdue, mais elle doit être allouée plus rapidement qu'elle n'est désallouée.
mardi
2
La seule fois où je veux que mon programme consomme une mémoire infinie, je ne peux pas le faire. (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.
Carcigenicate
14
Note to self: Sauvegardez le code avant de tester. L'introduction de mem-leaks pourrait planter IDE ...
Steenbergh
1
Je pense que vous devriez ajouter un autre défi de golf, similaire mais distinct, exigeant que le programme consomme de la mémoire plus rapidement qu'une fonction linéaire du temps. Pour le défi actuel , boucler pour toujours et attribuer un seul octet devrait suffire. Pour votre nouveau défi, cela serait insuffisant, mais boucler pour toujours et doubler la quantité de mémoire utilisée à chaque fois serait ok.
BenGoldberg

Réponses:

46

Funge-98 ( cfunge), 1 octet

9

J'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. cfungestocke 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 à 9plusieurs 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:

"NULL #(4

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, le Nreflet (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 le Nhaut de la pile - puis le programme tourne autour, chargeant une bibliothèque avec un nom de 4 lettres ( 4(; la NULLbibliothèque fait partie de cfungela bibliothèque standard de). NULLdéfinit toutes les lettres majuscules à faire refléter, donc le Lreflète, la#saute la charge de la bibliothèque sur le chemin du retour, les 4objets 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
2
Je vais juste accepter ça ...
dimanche
Est-il nécessaire que le nombre soit 9? Cela fonctionnerait-il également s'il était 5?
dimanche
Tout ce qui pousse vers la pile fonctionne (sauf éventuellement 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 choisir 9arbitrairement.
22
Inacceptable parce que je veux que ma réputation soit toujours 666.
tbodt
7
@tbodt Pas une vraie raison de ne pas accepter. Si vous le souhaitez, je vais répondre à votre question. Ensuite, lorsque vous acceptez, vous aurez encore 703 (notez que vous en avez 703 maintenant, pas 666).
NoOneIsHere
30

Brainfuck, 5 octets

+[>+]

Cela nécessite un interprète qui ne limite pas la longueur de la bande.

vsz
la source
2
Je suis presque sûr que c'est + [> +], sinon cela s'arrêterait à la première itération. ;)
Pâris Douady
Vous avez raison, désolé pour la faute de frappe.
vsz
40
Une des rares fois où une solution de brainfuck est compétitive ...
FlipTack
@ Flp.Tkc Mais il perd toujours. Peut-être qu'il gagnera un jour ...
NoOneIsHere
6
@SeeOneRhino: Il a déjà gagné une fois, battant toutes les langues de golf> codegolf.stackexchange.com/questions/8915/…
vsz
22

Bash + coreutils, 5

ou

Ruby, 5

`yes`

yesproduit une sortie sans fin. Mettre yesen 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.

Trauma numérique
la source
7
J'étais sur le point d'écrire la même chose et de l'appeler un programme Ruby.
GB
1
et Perl, je pense.
Abligh
18

Python, 16 octets

Conserve l'imbrication ajusqu'à ce qu'une erreur soit atteinte:

a=0
while 1:a=a,

Les premières itérations (en tuples) ressemblent à ceci:

0
(0,)
((0,),)
(((0,),),)

et ainsi de suite.

FlipTack
la source
18

> <> (Poisson), 1 octet

0

Essayez-le ici!

0 peut effectivement être substitué à tout nombre hexadécimal 1-f.

Explication

0in> <> crée simplement une boîte à code 1x1 pour le poisson. Il ajoute constamment un 0sur la pile, nage à droite, ce qui revient en boucle 0, l'ajoutant à nouveau à la pile. Cela durera pour toujours.

Redstarcoder
la source
2
Maintenant, je me demande dans combien d'autres langages à 2 dimensions cela fonctionne. La plupart d'entre eux sont basés sur des piles, après tout.
1
Fonctionne presque dans Cubix , mais il faut un caractère de tête .(ou tout caractère non-blanc) pour déplacer le 0dans la ligne d'exécution.
ETHproductions
1
Fonctionne dans Ouroboros , mais pas de la même manière: l’interprète essaie de lire 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 serait a(pousse 10 infiniment).
DLosc
12

Java 101 octets

class A{public void finalize(){new A();new A();}public static void main(String[]a){for(new A();;);}}

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

masterX244
la source
eh bien je me sens un peu bête de ne pas aller avec l'évidence maintenant, haha. J'oserais dire que c'est plus élégant que le mien
Poke,
1
Oui, votre code m'a rappelé ce fait avec le finalize () @poke
masterX244
Je pense que vous pourriez en faire plus court en remplaçant principal avec un initialiseur statique
tbodt
ne fonctionne que jusqu'à java6 et je n'ai que des versions supérieures
masterX244
2
haha en utilisant le ramasse-miettes pour provoquer une fuite! bonne idée :)
Mark K Cowan
12

Perl, 12 octets

{$"x=9;redo}

En perl, l' xopé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' redoopé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 :).

Ben Goldberg
la source
Vous m'avez battu à ça! Et le vôtre est plus court de trois octets.
Gabriel Benamy
1
Il suffisait de chercher sur ce site Web la plus petite boucle :). En outre, je l'avais initialement $_.=7dans ma boucle, mais je réalisais que si je pouvais l'utiliser, la x=mémoire s'épuiserait beaucoup plus rapidement, puis perldoc perlvarje choisirais quelque chose qui conviendrait.
BenGoldberg
{$^O++;redo}est un octet plus court quand ^Oest un seul chr(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.
Oleg V. Volkov
11

sed, 5 octets

Golfé

H;G;D

Utilisation (toute entrée fera l'affaire)

sed 'H;G;D' <<<""

A expliqué

#Append a newline to the contents of the hold space, 
#and then append the contents of the pattern space to that of the hold space.
H

#Append a newline to the contents of the pattern space, 
#and then append the contents of the hold space to that of the pattern space. 
G

#Delete text in the pattern space up to the first newline, 
#and restart cycle with the resultant pattern space.
D

Capture d'écran

entrez la description de l'image ici

Essayez-le en ligne!

Zeppelin
la source
2
Strictement parlant, il s’agit de GNU sed (le point-virgule n’est pas standard), mais une nouvelle ligne fonctionnerait aussi bien que le point-virgule.
R ..
10

Haskell, 23 19 octets

main=print$sum[0..]

Imprimer la somme d'une liste infinie

Angs
la source
C'est un bon moyen d'imposer l'évaluation, et c'est aussi très compact. +1
Esolanging Fruit
un compilateur pourrait très bien l'exécuter en mémoire O (1). Dans GHC, sumest défini comme foldl (+) 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?
Will Ness
@ WillNess Quelle pourrait être la réponse? sumne saura pas à l'avance que la liste est infinie et printqu'il faut en évaluer la somme en premier. Et oui, je l'ai compilé avec optimisations
Angs
il n'y aurait pas de réponse; mais le calcul se déroulerait dans l'espace O (1). Oups, grève que, en raison de la valeur par défaut Integer, les nombres sont illimités et que la mémoire exploitée par le résultat actuel de bignum augmente effectivement.
Will Ness
1
Juste pour clarifier, ce que je voulais dire, c'est que le calcul de sum xs = foldl (+) 0 xspeut fonctionner en pile constante, comme le ferait n'importe quelle boucle impérative . foldl' (+) 0 xssera certainement. Donc, la seule chose qui alloue de la mémoire avec certitude est le résultat provisoire de bignum.
Will Ness
9

C ++ (utilisant le compilateur g ++), 27 23 15 octets

Merci à 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.

main(){main();}

Solution alternative

Cette solution manque réellement de mémoire.

main(){for(;;new int);}

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.

==2582== LEAK SUMMARY:
==2582==    definitely lost: 15,104,008 bytes in 3,776,002 blocks
==2582==    indirectly lost: 0 bytes in 0 blocks
==2582==      possibly lost: 16 bytes in 4 blocks
==2582==    still reachable: 4 bytes in 1 blocks
==2582==         suppressed: 0 bytes in 0 blocks
Assistant de blé
la source
3
Le titre est trompeur; la question dit "écrivez un programme qui fonctionne pour toujours et alloue de la mémoire en permanence".
NobodyNada - Réintégrer Monica
Oh, je ne savais pas que vous aviez déjà répondu lorsque j'ai envoyé la mienne.
Neop
1
@Neop Eh bien, je ne savais pas que vous pourriez omettre int jusqu'à ce que je voie votre message , merci!
Wheat Wizard,
2
Non C++, juste son dialecte g ++: C ++ interdit d'appeler main; C ++ nécessite une int main...déclaration. Mais la solution est toujours soignée :-)
Martin Ba
1
En effet, C ++ interdit d'appeler main.
R ..
9

JAVA, 81 79 78 octets

JAVA (HotSpot) 71 70 octets

Plus court que les autres réponses Java au moment où j'ai posté (81, 79 octets plus tard):

class A{public static void main(String[]a){String x="1";for(;;)x+=x.intern();}}

Comme suggéré par @Olivier Grégoire, un octet supplémentaire peut être sauvegardé:

class A{public static void main(String[]a){for(String x="1";;)x+=x.intern();}}

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:

class A{public static void main(String[]a){String x="1";for(;;)x+=x;}}

Ce qui peut également bénéficier du conseil de @Olivier Grégoire:

class A{public static void main(String[]a){for(String x="1";;)x+=x;}}

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 xn'échappe jamais à la fonction locale. L'utilisation intern()évite ce problème car les chaînes internes finissent par être stockées dans un champ statique. Cependant, HotSpot génère un OutOfMemoryErrorpour ce code, donc je suppose que ça va.

Mise à jour: @Olivier Gregoire a également souligné que le x+=xcode peut être utilisé StringIndexOutOfBoundsExceptionplutôt que OOMlorsque beaucoup de mémoire est disponible. En effet, Java utilise le type 32 bits intpour indexer des tableaux (et les chaînes ne sont que des tableaux de char). Cela n'affecte pas la x+=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.

DepressedDaniel
la source
Bienvenue chez PPCG! Je ne connais pas très bien Java; que se passerait-il si vous veniez de le faire x+=x;?
ETHproductions
vous pouvez raser un point-virgule en mettant le x+=x.intern()derrière le dernier point-virgule de la boucle for
masterX244
Bonne réponse. Je savais qu'il devait y avoir quelque chose avec de la ficelle, internmais 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.
Poke
Si votre réponse dépend d'une implémentation spécifique de Java et ne serait pas nécessairement portable pour toutes les implémentations Java, vous pouvez placer les informations dans le titre (par exemple # 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.
1
humm ... x+=x;n'épuise pas la mémoire entière. Avec 64 Go, je reçois un StringIndexOutOfBoundsException, pas un MOO. Avec .intern()je reçois toujours le MOO.
Olivier Grégoire
8

Perl 6 , 13 octets

@= eager 0..*

Explication:

@ = stocker le résultat dans un tableau sans nom

eager rendre avide la liste suivante

0 .. * plage infinie commençant à zéro

Brad Gilbert b2gills
la source
8

///, 7 octets

/a/aa/a

Remplacez constamment apar aa, ad nauseum.

Steenbergh
la source
12
*aad naauseum
timothymh
1
* ad nauseam=>aad naauseaam
Aaron
Qu'en est- il //a/? Cela semble remplacer pour toujours `` (rien) par a, mais je ne sais pas si cela est spécifié exactement.
Cedric Reichenbach
6

Python 3, 16 octets

i=9
while 1:i*=i

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

artificiel
la source
Le titre implique que la mémoire doit être perdue. Mais cela ne perd pas réellement de mémoire. L'auteur devrait probablement clarifier.
Wheat Wizard
6

Rouille, 46 octets

fn main(){loop{std::mem::forget(Box::new(1))}}

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.

Harald Korneliussen
la source
6

TI-83 Hex Assembly, 7 octets

PROGRAM:M
:AsmPrgm
:EF6A4E
:C3959D
:C9

Crée des apparitions indéfiniment jusqu’à ce que ERR:MEMORYle système d’exploitation l’ envoie . Courez avec Asm(prgmM). Je compte chaque paire de chiffres hexadécimaux comme un octet.

Harry
la source
6

Python, 8 octets

2**9**99

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**10011 octets), mais naïvement, enregistrez la base 2 du nombre est

>>> 9**99.
2.9512665430652752e+94

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

Asmeurer
la source
5

Gelée , 3 2 octets

-1 octet grâce à Dennis ( Wwraps)

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

Jonathan Allan
la source
Si je comprends bien les règles, ça ‘ßdevrait être beaucoup.
Dennis
Est-ce que cela "alloue en permanence de la mémoire" (en pensant à Python qui maintient l'allocation constante pour les petits ints).
Jonathan Allan
1
C'est suffisant. devrait quand même faire l'affaire.
Dennis
5

Java 7, 106 octets

class A{public void finalize(){for(;;)Thread.yield();}public static void main(String[]a){for(;;)new A();}}

Moins de golf

class A{
    @Override
    public void finalize(){
        for(;;) {
            Thread.yield();
        }
    }
    public static void main(String[]a){
        for(;;){
            new A();
        }
    }
}

La finalizemé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 la mainboucle, 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

import sun.misc.*;class A{public static void main(String[]a)throws Exception{java.lang.reflect.Field f=Unsafe.class.getDeclaredField("theUnsafe");f.setAccessible(1>0);for(;;)((Unsafe)f.get(null)).allocateMemory(9);}}

Moins de golf

import sun.misc.*;
class A{
    public static void main(String[]a)throws Exception{
        java.lang.reflect.Field f=Unsafe.class.getDeclaredField("theUnsafe");
        f.setAccessible(true);
        Unsafe u = (Unsafe)f.get(null);
        for(;;) {
            u.allocateMemory(9);
        }
    }
}

C'est un amusement plus que toute autre chose. Cette réponse utilise la Unsafebibliothè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.allocateMemoryalloue 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 appeliez Unsafe.freeMemoryou que le volume de mémoire jvm soit saturé.

Poussée
la source
1
Je me demandais si je verrais Java ici.
Urne Octopus Magique
Le premier ne fonctionne-t-il que si le ramasse-miettes est exécuté dans un thread séparé?
dimanche
@tbodt oui mais je ne crois pas que ce ne soit jamais le cas. La collecte des ordures s'effectue dans un thread de démon appelé garbage collector
Poke
@Poke est-ce garanti? sinon la réponse est toujours correcte, mais vous devez préciser que cela ne fonctionne que si le ramasse-miettes s'exécute dans son propre thread
tbodt
@tbodt Je pense que oui, mais je ne suis pas certain, honnêtement.
Poke
5

Haskell, 24 octets

f x=f$x*x
main=pure$!f 9

Le problème principal à Haskell est de vaincre la paresse. maindoit avoir un certain IOtype, donc simplement appeler main=f 9ne fonctionnerait pas. Utiliser main=pure(f 9)soulève le type de f 9à un IOtype. Cependant, en utilisant des constructions comme main=pure 9ne fait rien, le 9est retourné ou affiché nulle part, mais simplement jeté, il n’est donc pas nécessaire d’évaluer l’argument de pure, donc main=pure(f 9)aucune mémoire ne sera allouée car elle fn’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, utiliser main=pure$!f 9évalue fet alloue donc continuellement plus de mémoire.

Laikoni
la source
Une fois compilé, le moteur d'exécution détecte la boucle et interrompt l'exécution
Angs
@Angs j'ai compilé avec ghc sur Windows et il continue d'allouer joyeusement la mémoire ... Je l'ai arrêté à 3 Go.
Laikoni
Utiliser des f x=f xœuvres aussi, non? (-2 octets)
wchargin
@ wchargin Je ne pense pas, f x=f xproduit une boucle infinie, mais sans allouer de nouvelle mémoire.
Laikoni
Sympa, provoquant l'explosion de mémoire par les calculs de bignum! f!x=x*f(x*x)devrait le rendre résistant aux optimisations.
Will Ness
5

dc, 7 octets

[ddx]dx

[ddx]pousse une chaîne contenant "ddx" dans la pile. dxle 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.

faubi
la source
Attendez, donc cela allouerait de manière exponentielle la mémoire si elle pouvait fonctionner en parallèle?
HyperNeutrino
5

Haskell (utilisant ghc 8.0.1), 11 octets

m@main=m>>m

Récursion sans queue. mains’appelle et puis à nouveau.

nimi
la source
Cela alloue-t-il sur le tas ou la pile? (Je peux le croire non plus; cela pourrait bien dépendre du compilateur Haskell utilisé.)
1
@ ais523: ça dépend. Haskell n'a pas de pile d'appels . Le système d'exécution RTS dispose d'une zone de mémoire pour la correspondance de modèle, également appelée "pile". Cette pile est allouée sur le tas. Honnêtement, je ne sais pas ce qui se passe ici, car le programme échoue avec 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.
nimi
1
@ ais523: il semble y avoir un bogue dans les informations de mémoire du message d'erreur ghc, il est donc difficile de dire ce qui se passe exactement.
nimi
Compilé sur GHC 7.10.3 sur Ubuntu, cela semble nécessiter une quantité de mémoire constante, même lorsque les optimisations sont désactivées
Angs
@Angs: hmm, j'utilise ghc 8.0.1 sur MacOS. Je vais éditer ça.
nimi
5

C (linux), 23 octets

main(){while(sbrk(9));}

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 le VIRTchamp de topsortie. 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

main(){while(malloc(9));}

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éments malloc()internes écrivent nécessairement .

Trauma numérique
la source
Avec malloc, vous n'écrivez pas directement dans la mémoire car malloc n'initialise rien. La mémoire n'est allouée que parce que malloc a besoin de mémoire interne pour la gestion de la mémoire. La réponse n’est donc pas vraiment standard mais j’imagine que cela fonctionne partout quand même.
Antzi
@ Antzi Oui. Cependant, je pense que cela fonctionne toujours car, même si la mémoire utilisateur n’est pas réellement allouée avant qu’elle ne soit écrite, chaque malloc()bloc ed doit toujours avoir son propre espace alloué réel. Cela fonctionne sur macOS et Ubuntu.
Digital Trauma
Dans la question de l’écriture de chaque page, la condition est plutôt dépourvue de sens; même si vous voulez supposer qu'un système d'exploitation ne fait pas une comptabilité de validation appropriée, quels que soient les détails de la mise en œuvre, un montant non nul de comptabilité est nécessaire par allocation. Qu'elle soit adjacente à l'allocation (provoquant le toucher des pages) ou non, elle consommera éventuellement des quantités de mémoire arbitraires pour la tenue de livres avec (nécessairement) des données non nulles.
R ..
Vous pourriez l'obtenir d'un octet plus petit 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 sur main...
R ..
Si vous remplacez malloc (9) par calloc (9,9), il y aura suffisamment de mémoire allouée pour 9 instances d'un bloc de 9 octets (soit entre 81 et 144 octets, en fonction de l'alignement. Toutefois, et plus important encore, calloc ( ) remplira le bloc de mémoire de zéro, forçant le système d'exploitation sous-jacent à lui allouer de la mémoire
CSM
5

Perl, 4 octets

do$0

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.

primo
la source
Sympa et court, bien que cela ne gaspille pas la mémoire rapidement comme la mienne.
BenGoldberg
4

Raquette, 13 octets

(let l()(l)1)

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.

Winny
la source
Pouvez-vous expliquer comment cela fonctionne?
dimanche
1
oh, alors c'est définir lcomme une fonction qui fait la récursion sans appel en arrière. Je dirais que ça compte.
dimanche
@tbodt oui tu as raison sur l'argent
Winny
4

JavaScript 22 21 17 16 15 octets

for(a=0;;)a=[a]

Sauvegardé 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)

f=a=>f([a]);f()
Lmis
la source
1
Sur votre deuxième exemple avec ES6, ne pourriez-vous pas simplement faire f=_=>f();f()? 12 octets
mordu
@bitten je ne suis pas sûr. Si cela compte de faire sauter la pile d'appels, alors celui-là sans les appels de queue appropriés serait le chemin à parcourir. Avec le TCO, je ne pense pas qu'il y aurait une fuite de mémoire, n'est-ce pas?
Lmis
les deux font sauter la pile d'appels pour moi . Je ne connais pas vraiment les appels de queue, je ne peux donc pas en parler.
mordu
1
ah je vois, je ne savais pas comment la tienne perdait de la mémoire
mordue
1
Vous pouvez enlever a=0. La première itération aboutiraita=[undefined]
Florent
4

Ruby, 11 octets

loop{$*<<9}

Conserve de poussée 9sur $*, qui est un tableau contenant initialement les arguments de ligne de commande pour le processus Ruby.

Daniero
la source
4

05AB1E , 2 octets

[A

Essayez-le en ligne! Continuons simplement à pousser abcdefghijklmnopqrstuvwyxzsur la pile pour l'éternité.

Toutes les solutions possibles à 2 octets:

[  # Infinite loop.
 A # Push alphabet.
 0 # Push 0.
 1 # Push 1.
 2 # Push 2.
 3 # Push 3.
 4 # Push 4.
 5 # Push 5.
 6 # Push 6.
 7 # Push 7.
 8 # Push 8.
 9 # Push 9.
 T # Push 10.
 X # Push 1.
 Y # Push 2.
 ® # Push -1.
 ¶ # Push \n.
 º # Push len(stack) > 0, so 0 once then 1 for eternity.
 ð # Push a space.
 õ # Push an empty string.
 ¾ # Push 0.
 ¯ # Push [].
 M # Push -inf.
 ) # Wrap current stack in an array.
Urne Magique De Pieuvre
la source
Très complet! Agréable.
Timothymh
3

Python, 35 octets

def f(a=[]):a.append(a)
while 1:f()

a est jamais libéré et ne fait que grossir jusqu'à ce que vous frappez un MemoryError

Vous pouvez voir l'exécution sur Python Tutor .

Noelkd
la source
1
Pouvez-vous faire a+=a,?
Cyoce
Pas besoin d'une fonction, voici mon golf de celui - ci
FlipTack
@ Flp.Tkc la question a été modifiée après que j'ai écrit cette réponse j'aurais fait ce que vous avez fait (+ - quelques caractères) si c'était dans son format actuel.
Noelkd
3

TI-BASIC, 8

:Lbl A
:While 1
:Goto A

(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 Whilefermeture anticipée prévue par un Endé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 utilisons Gotopour quitter la boucle (donc no Endest exécuté pour retirer la chose de la pile), on la Whilevoit à nouveau, la chose est poussée à nouveau, etc. Donc, elle continue de les pousser jusqu'à ce que vous obteniezERR:MEMORY

Harold
la source