introduction
Vous êtes probablement familiarisé avec les bombes zip , XML , etc. Le défi ici est d'abuser d'un compilateur de la même manière.
Défi
Ecrivez du code source qui occupe 512 octets ou moins et qui se compile dans un fichier qui occupe le plus d’espace possible. Le plus grand fichier de sortie gagne!
Règles
OK, il y a donc quelques clarifications, définitions et restrictions importantes;
- La sortie de la compilation doit être un fichier ELF , un exécutable portable Windows (.exe) ou un bytecode virtuel pour la JVM ou le CLR de .Net (d'autres types de bytecode virtuel sont également susceptibles de convenir, le cas échéant). Mise à jour: la sortie .pyc / .pyo de Python compte également .
- Si votre langue de choix ne peut pas être compilée directement dans l'un de ces formats, la transpilation suivie de la compilation est également autorisée ( Mise à jour: vous pouvez transpiler plusieurs fois, du moment que vous n'utilisez jamais la même langue plus d'une fois ).
- Votre code source peut comprendre plusieurs fichiers, voire des fichiers de ressources, mais la taille totale de tous ces fichiers ne doit pas dépasser 512 octets.
- Vous ne pouvez utiliser aucune autre entrée que vos fichiers source et la bibliothèque standard de votre langue de choix. La liaison statique des bibliothèques standard est acceptable si elle est prise en charge. Plus précisément, pas de bibliothèques tierces ni de bibliothèques de système d'exploitation.
- Il doit être possible d'appeler votre compilation à l'aide d'une commande ou d'une série de commandes. Si vous avez besoin d'indicateurs spécifiques lors de la compilation, ceux-ci sont pris en compte dans votre limite d'octets (par exemple, si votre ligne de compilation est
gcc bomb.c -o bomb -O3 -lm
, la-O3 -lm
partie (7 octets) sera comptée (notez que l'espace initial initial n'est pas compté). - Les préprocesseurs ne sont autorisés que s’ils constituent une option de compilation standard pour votre langue.
- L’environnement vous appartient, mais dans l’intérêt de rendre ceci vérifiable, veuillez vous en tenir aux versions récentes du compilateur (disponibles) et aux systèmes d’exploitation (et bien sûr spécifier celui que vous utilisez).
- Il doit compiler sans erreurs (les avertissements sont OK), et planter le compilateur ne compte pour rien.
- Ce que votre programme fait en réalité n’a aucune importance, même s’il ne peut s'agir de rien de malicieux. Il n'est même pas nécessaire de pouvoir commencer.
Exemple 1
Le programme C
main(){return 1;}
Compilé avec Apple LLVM version 7.0.2 (clang-700.1.81)
OS X 10.11 (64 bits):
clang bomb.c -o bomb -pg
Produit un fichier de 9228 octets. La taille totale de la source est de 17 + 3 (pour le -pg
) = 20 octets, ce qui est facilement dans la limite de taille.
Exemple 2
Le programme Brainfuck:
++++++[->++++++++++++<]>.----[--<+++>]<-.+++++++..+++.[--->+<]>-----.--
-[-<+++>]<.---[--->++++<]>-.+++.------.--------.-[---<+>]<.[--->+<]>-.
Transpilé avec awib à c avec:
./awib < bomb.bf > bomb.c
Puis compilé Apple LLVM version 7.0.2 (clang-700.1.81)
sous OS X 10.11 (64 bits):
clang bomb.c
Produit un fichier de 8464 octets. Le total des entrées ici est de 143 octets ( @lang_c
étant la valeur par défaut pour awib, il n’a pas besoin de l’ajouter au fichier source, et il n’ya pas d’indicateur spécial sur ces commandes).
Notez également que dans ce cas, le fichier temporaire bomb.c fait 802 octets, mais cela ne compte ni dans la taille de la source ni dans la taille de la sortie.
Note finale
Si vous obtenez une sortie de plus de 4 Go (peut-être si quelqu'un trouve un préprocesseur complet), le concours s'adressera à la plus petite source produisant un fichier d'au moins cette taille (il n'est tout simplement pas pratique de tester des soumissions trop volumineuses). .
Réponses:
C, (14 + 15) = source de 29 octets, exécutable exécutable de 17 179 875 837 (16 Go)
Merci à @viraptor pour 6 octets de moins.
Merci à @hvd pour 2 octets désactivés et une taille d’exécutable x4.
Ceci définit la
main
fonction comme un grand tableau et initialise son premier élément. Cela oblige GCC à stocker l'intégralité de la matrice dans l'exécutable résultant.Étant donné que cette matrice dépasse 2 Go, nous devons fournir l'
-mcmodel=medium
indicateur à GCC. Les 15 octets supplémentaires sont inclus dans la partition, conformément aux règles.Ne vous attendez pas à ce que ce code fasse quoi que ce soit de bien lorsqu'il est exécuté.
Compiler avec:
Il m'a fallu un certain temps pour tester la suggestion de @ hvd et trouver une machine suffisamment puissante pour la gérer. Finalement, j'ai trouvé une vieille machine virtuelle RedHat 5.6 de non-production avec 10 Go de RAM, 12 Go de swap et / tmp définie sur une grande partition locale. La version de GCC est 4.1.2. Le temps total de compilation est d’environ 27 minutes.
la source
a
. Vous pouvez simplement utilisermain[1<<30]={1};
1<<30
alors7<<28
pourrait être une option.C #, environ 1 minute pour compiler, 28 Mo de sortie en binaire:
Ajouter plus de Y augmentera la taille de manière exponentielle.
Une explication de Pharap selon la demande de @Odomontois:
Cette réponse abuse des paramètres d'héritage et de type pour créer une récursivité. Pour comprendre ce qui se passe, il est plus facile de commencer par simplifier le problème. Considérons
class X<A> { class Y : X<Y> { Y y; } }
, qui génère la classe génériqueX<A>
, qui a une classe interneY
.X<A>.Y
hériteX<Y>
, a doncX<A>.Y
aussi une classe interneY
, qui est alorsX<A>.Y.Y
. Cela a alors aussi une classe interneY
, et cette classe interneY
a une classe interne,Y
etc. Cela signifie que vous pouvez utiliser scope resolution (.
) à l'infini, et chaque fois que vous l'utilisez, le compilateur doit déduire un autre niveau d'héritage et de paramétrage du type. .En ajoutant des paramètres de type supplémentaires, le travail que le compilateur doit effectuer à chaque étape est encore accru.
Considérez les cas suivants:
Dans le
class X<A> { class Y : X<Y> { Y y;} }
type paramA
a un type deX<A>.Y
.Dans le
class X<A> { class Y : X<Y> { Y.Y y;} }
type paramA
a un type deX<X<A>.Y>.Y
.Dans le
class X<A> { class Y : X<Y> { Y.Y.Y y;} }
type paramA
a un type deX<X<X<A>.Y>.Y>.Y
.En
class X<A,B> { class Y : X<Y,Y> { Y y;} }
type paramA
estX<A,B>.Y
etB
estX<A,B>.Y
.En
class X<A> { class Y : X<Y> { Y.Y y;} }
type paramA
estX<X<A,B>.Y, X<A,B>.Y>.Y
etB
estX<X<A,B>.Y, X<A,B>.Y>.Y
.En
class X<A> { class Y : X<Y> { Y.Y.Y y;} }
type paramA
estX<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Y
etB
estX<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Y
.À la suite de ce modèle, on ne peut imaginer 1 le travail du compilateur devrait faire pour en déduire ce que
A
pourE
sont dansY.Y.Y.Y.Y.Y.Y.Y.Y
la définitionclass X<A,B,C,D,E>{class Y:X<Y,Y,Y,Y,Y>{Y.Y.Y.Y.Y.Y.Y.Y.Y y;}}
.1 Vous pouvez le comprendre, mais vous aurez besoin de beaucoup de patience et intellisense ne vous aidera pas ici.
la source
Y
s .Python 3, source de 13 octets, 9,057,900,463 octets (8.5GiB) .pyc-file
Éditer : Le code a été remplacé par la version ci-dessus après avoir réalisé que les règles stipulaient que la taille de sortie au-delà de 4 Go importait peu et que le code de celle-ci était légèrement plus court. Le code précédent - et plus important encore l'explication - peut être trouvé ci-dessous.
Python 3, source 16 octets,> 32 To .pyc-file (si vous avez assez de mémoire, d'espace disque et de patience)
Explication: Python 3 effectue un repliement constant, et vous obtenez rapidement de grands nombres avec une exponentation. Le format utilisé par les fichiers .pyc stocke la longueur de la représentation entière sur 4 octets, bien que la limite semble en réalité ressembler davantage
2**31
. Par conséquent, si vous utilisez simplement l’exponentation pour générer un grand nombre, la limite semble générer 2 Go. pyc depuis une source de 8 octets. (19**8
est un peu timide8*2**31
, a donc1<<19**8
une représentation binaire un peu moins de 2 Go; la multiplication par huit est parce que nous voulons des octets, pas des bits)Cependant, les n-uplets sont également immuables et multiplier un tuple est toujours plié, nous pouvons donc dupliquer ce blob de 2 Go autant de fois que nous le souhaitons, au moins au moins
2**31
, probablement. Le passage4**7
à 32 To a été choisi simplement parce que c’était le premier exposant où je pouvais trouver qui battait la réponse précédente de 16 To.Malheureusement, avec la mémoire que j'ai sur mon propre ordinateur, je n'ai pu tester cela que jusqu'à un multiplicateur de 2, c'est-à-dire.
(1<<19**8,)*2
, qui a généré un fichier de 8,5 Go, ce qui, j’espère, montre que la réponse est réaliste (c’est-à-dire que la taille du fichier n’est pas limitée à 2 ** 32 = 4 Go).De plus, je ne sais pas pourquoi la taille du fichier que j’avais lors des tests était de 8,5 Go au lieu des 4 Go que j’espérais, et le fichier est suffisamment gros pour que je n’aie pas envie de le fouiller pour le moment.
la source
(1<<19**8,)*2
? 4 Go suffisent.1<<18
sur ma machine (1,5 Go), mais je le testerai plus tard sur Linux, où je pense que cela fonctionnera avec la totalité des 8 Go (je ne vais pas essayer la version 32 To!)python -m py_compile asd.py
pour générer le fichier .pyc."Template Haskell" permet de générer du code Haskell lors de la compilation à l'aide de Haskell, ce qui en fait un pré-processeur complet.
Voici ma tentative, paramétrée par une expression numérique arbitraire
FOO
:La magie est le code à l'intérieur de "l'épissure"
$(...)
. Ceci sera exécuté au moment de la compilation, pour générer un AST Haskell, qui sera greffé sur l'AST du programme à la place de l'épissure.Dans ce cas, nous faisons un simple AST représentant le littéral
0
, nous le reproduisonsFOO
pour en faire une liste, puis nous utilisonsListE
leLanguage.Haskell.TH
module pour transformer cette liste d'AST en un seul gros AST, représentant le littéral[0, 0, 0, 0, 0, ...]
.Le programme résultant est équivalent à
main = print [0, 0, 0, ...]
avecFOO
répétitions de0
.Pour compiler en ELF:
Cela pèse 83 octets (66 pour le code Haskell et 17 pour l’
-XTemplateHaskell
argument), plus la longueur deFOO
.Nous pouvons éviter l'argument du compilateur et juste compiler avec
ghc
, mais nous devons mettre{-# LANGUAGE TemplateHaskell#-}
au début, ce qui place le code jusqu'à 97 octets.Voici quelques exemples d'expressions pour
FOO
, et la taille du binaire résultant:J'ai manqué de RAM avec la compilation
(2^20)
.On peut aussi faire une liste infinie, en utilisant à la
repeat
place dereplicate FOO
, mais cela empêche le compilateur de s’arrêter;)la source
[...].replicate (2^10)<$>[|0|])
). Je n'ai pas d'expérience avec Haskell. des astuces sur comment faire cette compilation?<$>
fonction est largement utilisée dans Haskell, mais n'a été déplacée que vers le "prélude" (l'ensemble des fonctions disponibles par défaut) dans GHC 7.10. Pour les versions antérieures, vous devrez ajouterimport Control.Applicative;
après laimport
déclaration existante . Je viens d'essayer avec GHC 7.8.4 et cela fonctionne.C ++, 250 + 26 = 276 octets
C'est la fonction Ackermann implémentée dans les templates. Je ne suis pas capable de compiler avec
h=a<4,2>::n;
ma petite machine (6 Go), mais j'ai réussi àh=a<3,14>
obtenir un fichier de sortie de 26Mo. Vous pouvez ajuster les constantes pour qu'elles atteignent les limites de votre plate-forme. Consultez l'article lié de Wikipedia pour obtenir des conseils.Requiert un
-g
indicateur pour GCC (car ce sont tous les symboles de débogage qui consomment réellement de l'espace) et une profondeur de modèle supérieure à celle par défaut. Ma ligne de compilation a fini commeInformations sur la plateforme
la source
A+B
dans chaque classe, maintenant j'y pense ...ASM, 61 octets (source de 29 octets, 32 octets pour les drapeaux), exécutable de 4 294 975 320 octets
Compiler avec
gcc the_file.s -mcmodel=large -Wl,-fuse-ld=gold
la source
1<<30
est assez bon pour C. Puisqu'il s'agit d'un assembleur, la taille est en octets.as
parvient à passer àld
, maisld
échoue avec cela . Pas même-mcmodel=medium
semble aider.gold
éditeur de liens:gcc -fuse-ld=gold ...
compile / links ... eek! Terminé en 1:29 (89 secondes) et une taille de 1 073 748 000 octets.gcc -o g g.s -mcmodel=large -Wl,-fuse-ld=gold
. Compte final:,4,294,975,320 bytes
avec 32 octets supplémentaires ajoutés à la longueur du programme pour-mcmodel=large -Wl,-fuse-ld=gold
. Il est à noter que l'en-tête est incorrect. la source est de 29 octets (sans les indicateurs supplémentaires ajoutés).1<<33
, je me suis retrouvé avec un8,589,942,616
exécutable d'octet.Voici ma réponse C de 2005. Produirait un binaire de 16 To si vous aviez 16 To de RAM (ce n'est pas le cas).
la source
Pré-processeur en clair: entrée de 214 octets, sortie de 5 Mo
Inspiré par mon pré-processeur du monde réel, échouez ici .
Les expériences montrent que chaque niveau de
#define
s (comme prévu) rend la sortie environ dix fois plus grande. Mais comme cet exemple a pris plus d’une heure pour compiler, je n’ai jamais passé à «G».la source
Java, source 450 + 22 = 472 octets, fichier de classe ~ 1 Go
B.java (version golfée, avertissement lors de la compilation)
B.java (version non golfée)
Compilation
Explication
Cette bombe utilise des processeurs d'annotation. Il faut 2 passes de compilation. La première passe construit la classe de processeur
B
. Au cours de la deuxième étape, le processeur crée un nouveau fichier sourceC.java
et le compileC.class
avec une taille en1,073,141,162
octets.Il existe plusieurs limitations lorsqu’on essaie de créer un fichier de classe volumineux:
error: UTF8 representation for string "iiiiiiiiiiiiiiiiiiii..." is too long for the constant pool
.error: too many constants
.class
fichier. Si j'augmente16380
à16390
dans le code ci - dessus le compilateur ne retourne jamais..java
fichier. L'augmentation16380
de16400
dans le code ci-dessus entraîne:An exception has occurred in the compiler (1.8.0_66). Please file a bug ...
suivi de ajava.lang.IllegalArgumentException
.la source
try..finally
(le code dans le dernier bloc est dupliqué pour les cas normaux et exceptionnels) et le bloc d'initialisation (le code du bloc d'initialisation est ajouté à chaque constructeur)ä
par uni
et ajusté les nombres. Maintenant, la bombe devrait créer une classe de 1 Go sur tout système sans aucun problème d’encodage. Cependant, il a maintenant besoin de beaucoup plus de mémoire.C, source de 26 octets, sortie de 2.139.103.367 octets, programme valide
Compilé avec:
gcc cbomb.c -o cbomb
(gcc version 4.6.3, Ubuntu 12.04, ~ 77 secondes)Je pensais que je pourrais essayer de voir quelle taille je pourrais faire un programme valide sans utiliser aucune option de ligne de commande. J'ai eu l'idée de cette réponse: https://codegolf.stackexchange.com/a/69193/44946 de Digital Trauma. Voir les commentaires pour savoir pourquoi cela est compilé.
Comment cela fonctionne: Le
const
supprime l'indicateur d'écriture des pages du segment, de sorte que main peut être exécuté. Le195
est le code machine Intel pour un retour. Et puisque l’architecture Intel est little-endian, c’est le premier octet. Le programme se terminera quel que soit le code de démarrage mis dans le registre eax, probablement 0.Ce n'est que d'environ 2 Go, car l'éditeur de liens utilise des valeurs signées 32 bits pour les décalages. Il est 8 mégawatts plus petit que 2 gig, car le compilateur / éditeur de liens a besoin d’un peu d’espace pour fonctionner et c’est le plus important que je puisse obtenir sans erreurs d’éditeur de liens - ymmv.
la source
Boo , 71 octets. Temps de compilation: 9 minutes. 134 222 236 octet exécutable
Utilise une macro
R
(pour Repeat) pour que le compilateur multiplie l'instruction d'incrémentation un nombre arbitraire de fois. Aucun indicateur de compilateur spécial n'est nécessaire; enregistrez simplement le fichier sousbomb.boo
et appelez le compilateur avecbooc bomb.boo
pour le construire.la source
2**e
-Qu'est-ce que c'est? Essayez9**e
!Kotlin , source 90 octets, 177416 octets (173 Ko) binaire compilé JVM
Techniquement, vous pouvez prolonger cette durée en imbriquant davantage l'expression. Toutefois, le compilateur se bloque avec une
StackOverflow
erreur si vous augmentez la récursivité.la source
C ++, 214 octets (aucune option de compilation spéciale n'est requise)
Il s'agit d'une récursion de modèle bidimensionnelle assez simple (la profondeur de récursivité est la racine carrée du nombre total de modèles émis, elle ne dépassera donc pas les limites de la plate-forme), avec une petite quantité de données statiques dans chacun.
Le fichier objet généré avec
g++ 4.9.3 x86_64-pc-cygwin
est 2567355421 octets (2,4 Go).L'augmentation de la valeur initiale au-dessus de 80 divise l'assembleur cygwin gcc (trop de segments).
Aussi,
99999
peut être remplacé par9<<19
ou similaire pour une taille accrue sans changer le code source ... mais je ne pense pas avoir besoin d'utiliser plus d'espace disque que ce que je suis déjà;)la source
-c
drapeau de compilation pour arrêter l'éditeur de liens (2 octets supplémentaires), et je ne suis pas sûr de pouvoir accepter la sortie .o (pas l'une de celles que j'ai énumérées). Pourtant, j'aime bien, alors +1.Scala - source de 70 octets, résultat de 22980842 octets (après le pot)
Cela produit 9 5 (environ 59 000) fichiers de classe spécialisés, qui sont placés dans un fichier jar d’environ 23 Mo. En principe, vous pouvez continuer si vous avez un système de fichiers capable de gérer autant de fichiers et de disposer de suffisamment de mémoire.
(Si la commande jar doit être incluse, il s'agit de 82 octets.)
la source
error: java.lang.OutOfMemoryError: GC overhead limit exceeded
. Pourriez-vous également documenter la commande requise pour la compilation?scalac -J-Xmx12G X.scala
c'est ce que j'ai utilisé. Je n'ai pas testé combien il a réellement besoin.error: error while loading AnnotatedElement, class file '/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/rt.jar(java/lang/reflect/AnnotatedElement.class)' is broken (bad constant pool tag 18 at byte 76) one error found
Pouvez-vous spécifier la version scala et java (peut-être aussi la plate-forme)? J'ai utilisé scalac 2.9.2 et OpenJDK 1.8.0_66-internal-b17, sur debian 8 x86-64.java version "1.8.0_72-ea" Java(TM) SE Runtime Environment (build 1.8.0_72-ea-b05) Java HotSpot(TM) 64-Bit Server VM (build 25.72-b05, mixed mode)
,$ scala -version Scala code runner version 2.11.7 -- Copyright 2002-2013, LAMP/EPFL
C, 284 octets + 2 pour le
-c
ingcc bomb.c -o bomb.o -c
; sortie: 2 147 484 052 octetsla source
Boo, bien plus que ce que tu peux en attendre
la source
Python 3:
Bombe de pénétration
la source