Construire une bombe de compilation


372

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


Si vous utilisez un transpiler, le code source de sortie doit-il être inférieur à 512 octets, ainsi que le code source d'entrée?
Trichoplax

3
La transpilation répétée est-elle autorisée?
Orlp

3
@ LegionMammal978 oui, il doit produire l'un des types de fichiers que j'ai spécifiés. Mais si vous pensez avoir trouvé quelque chose qui est plus une machine virtuelle qu'un langage interprété, posez-lui des questions spécifiques et il est possible que je le permette (c'est un peu subjectif, je voulais donc être très restrictif pour commencer, avec l'option de l'ouvrir)
Dave

3
@trichoplax Je n'étais pas au courant de cela, mais d'après certaines lectures, cela ressemble à oui; la compilation en bytecode Python compte absolument Donc, pour python, la taille de sortie serait la taille totale de tous vos fichiers pyc / pyo. Je mettrai à jour la question bientôt avec ces mises à jour basées sur les commentaires.
Dave

2
@MartinRosenau - WGroleau a déjà posé une question similaire; Il est courant dans les défis de codage de pouvoir utiliser tout ce qui existait déjà au début du défi.
Dave

Réponses:


441

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 mainfonction 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=mediumindicateur à GCC. Les 15 octets supplémentaires sont inclus dans la partition, conformément aux règles.

main[-1u]={1};

Ne vous attendez pas à ce que ce code fasse quoi que ce soit de bien lorsqu'il est exécuté.

Compiler avec:

gcc -mcmodel=medium cbomb.c -o cbomb

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.

En raison de la charge du processeur et de la RAM, il est déconseillé de procéder à cette compilation sur une machine liée à la production à distance .



13
Je joue contre ma solution ici, mais ... tu n'as pas besoin a. Vous pouvez simplement utilisermain[1<<30]={1};
viraptor

38
Oh mon. C'est mal. X s'est figé pendant plusieurs minutes pour essayer de compiler ce code. Je commençais à chercher un autre ordinateur pour ssh éventuellement et de tuer le processus gcc avant qu'il ne revienne à la vie. Btw. Si vous voulez une valeur plus grande que 1<<30alors 7<<28pourrait être une option.
Kasperd

33
> 4 Go? Cela a dégénéré rapidement
Wayne Werner

18
Au cas où quelqu'un se demanderait pourquoi cela compile: stackoverflow.com/questions/34764796/…
TC

206

C #, environ 1 minute pour compiler, 28 Mo de sortie en binaire:

class X<A,B,C,D,E>{class Y:X<Y,Y,Y,Y,Y>{Y.Y.Y.Y.Y.Y.Y.Y.Y y;}}

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érique X<A>, qui a une classe interne Y. X<A>.Yhérite X<Y>, a donc X<A>.Yaussi une classe interne Y, qui est alors X<A>.Y.Y. Cela a alors aussi une classe interne Y, et cette classe interne Ya une classe interne, Yetc. 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 param Aa un type de X<A>.Y.
Dans le class X<A> { class Y : X<Y> { Y.Y y;} }type param Aa un type de X<X<A>.Y>.Y.
Dans le class X<A> { class Y : X<Y> { Y.Y.Y y;} }type param Aa un type de X<X<X<A>.Y>.Y>.Y.
En class X<A,B> { class Y : X<Y,Y> { Y y;} }type param Aest X<A,B>.Yet Best X<A,B>.Y.
En class X<A> { class Y : X<Y> { Y.Y y;} }type param Aest X<X<A,B>.Y, X<A,B>.Y>.Yet Best X<X<A,B>.Y, X<A,B>.Y>.Y.
En class X<A> { class Y : X<Y> { Y.Y.Y y;} }type param Aest X<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Yet Best X<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 Apour Esont dans Y.Y.Y.Y.Y.Y.Y.Y.Yla définition class 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.


14
Cela ressemble plus à la sorte de folie que je m'attendais! On dirait que je vais réinstaller Mono…
Dave

31
Pouvez-vous fournir une explication de cet effet notoire?
Odomontois

16
+1 pour faire plus que simplement initialiser un grand tableau.
Stig Hemmer

6
Voici un exemple utilisant Try Roslyn et juste 3 Ys .
Kobi

10
J'ai vu cette question et a immédiatement pensé à vous. Agréable!
Eric Lippert

154

Python 3, source de 13 octets, 9,057,900,463 octets (8.5GiB) .pyc-file

(1<<19**8,)*2

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

(1<<19**8,)*4**7

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**8est un peu timide 8*2**31, a donc 1<<19**8une 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 passage 4**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.


2
+1, mais pourquoi pas (1<<19**8,)*2? 4 Go suffisent.
Akangka

2
@ChristianIrwan: Oui, j'avais oublié cette règle, je ne l'avais compris que depuis quelques minutes et je n'avais pas encore déterminé le type de montage que je devais effectuer. :-)
Aleksi Torhamo

1
Agréable. Comme il ne reste que 13 octets, nous avons enfin un challenger à la réponse affichée en premier! Je n'ai pu confirmer que 1<<18sur 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!)
Dave

1
@Dave: La taille exacte pourrait dépendre de la version (1,5 Go, ça sonne bizarre, quoi qu'il arrive); J'utilisais Python 3.3.5 et utilisais python -m py_compile asd.pypour générer le fichier .pyc.
Aleksi Torhamo

3
IIRC, python utilise 30 bits par mot de 32 bits dans sa représentation entière

130

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

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

import Language.Haskell.TH;main=print $(ListE .replicate FOO<$>[|0|])

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 reproduisons FOOpour en faire une liste, puis nous utilisons ListEle Language.Haskell.THmodule 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, ...]avec FOOrépétitions de 0.

Pour compiler en ELF:

$ ghc -XTemplateHaskell big.hs
[1 of 1] Compiling Main             ( big.hs, big.o )
Linking big ...
$ file big
big: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /nix/store/mibabdfiaznqaxqiy4bqhj3m9gaj45km-glibc-2.21/lib/ld-linux.so.2, for GNU/Linux 2.6.32, not stripped

Cela pèse 83 octets (66 pour le code Haskell et 17 pour l’ -XTemplateHaskellargument), plus la longueur de FOO.

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:

FOO         FOO size    Total size    Binary size
-------------------------------------------------
(2^10)      6B          89B           1.1MB
(2^15)      6B          89B           3.6MB
(2^17)      6B          89B           12MB
(2^18)      6B          89B           23MB
(2^19)      6B          89B           44MB

J'ai manqué de RAM avec la compilation (2^20).

On peut aussi faire une liste infinie, en utilisant à la repeatplace de replicate FOO, mais cela empêche le compilateur de s’arrêter;)


46
Bienvenue dans Programmation Puzzles et Code Golf. C'est une réponse brillante , en particulier pour un nouvel utilisateur de ce site. Si vous avez besoin d'aide (ce dont je doute), n'hésitez pas à demander.
wizzwizz4

3
@ wizzwizz4: Oui, c'est une réponse brillante. C'est essentiellement la même chose que la mienne, à l'exception du fait qu'en Haskell, une métaprogrammation nécessite une directive spéciale du compilateur. ;)
Mason Wheeler

2
Quand je compile avec GHC 7.8.3, je reçois le message "Pas dans la portée: '<$>'" (je règle le code sur [...].replicate (2^10)<$>[|0|])). Je n'ai pas d'expérience avec Haskell. des astuces sur comment faire cette compilation?
Dave

38
Dommage que le modèle haskell ne soit pas assez fainéant pour diffuser un exécutable infini.
PyRulez

1
Hi @Dave, la <$>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 ajouter import Control.Applicative;après la importdéclaration existante . Je viens d'essayer avec GHC 7.8.4 et cela fonctionne.
Warbo

80

C ++, 250 + 26 = 276 octets

template<int A,int B>struct a{static const int n;};
template<int A,int B>const int a<A,B>::n=a<A-1,a<A,B-1>::n>::n;
template<int A>struct a<A,0>{static const int n=a<A-1,1>::n;};
template<int B>struct a<0,B>{static const int n=B+1;};
int h=a<4,2>::n;

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 -gindicateur 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 comme

g++ -ftemplate-depth=999999 -g -c -o 69189.o 69189.cpp

Informations sur la plateforme

g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2
Linux 3.13.0-46-generic #79-Ubuntu SMP x86_64 GNU/Linux

J'aime vraiment celui-ci, mais je ne suis pas sûr de pouvoir accepter une sortie .o, car j'ai dit ELF / .exe / etc. (et compiler ceci optimise complètement le tout!). Toujours, +1 (et confirmé)
Dave

4
Mise à jour: Comme Ben Voigt souligne sur sa réponse, GCC sous Linux ne génère des fichiers ELF comme .o sortie, et je l' ai été en mesure de confirmer la <3,14> variante avec elle, donc yup - ceci est valable.
Dave

17
Je m'attendais à quelque chose d'absurde à sortir des modèles C ++. Je ne m'attendais pas à la fonction Ackermann.
Marc

Fibonacci ne vous donnera-t-il pas un code plus petit et un meilleur contrôle de la taille de la sortie?
Will Ness

1
Mais nous voulons un code plus gros! Fibonacci donne presque la même taille que le code linéaire pur (mais le temps de compilation est plus long que celui du linéaire). Vous pourriez certainement vous amuser avec un tableau statique de taille A+Bdans chaque classe, maintenant j'y pense ...
Toby Speight

65

ASM, 61 octets (source de 29 octets, 32 octets pour les drapeaux), exécutable de 4 294 975 320 octets

.globl main
main:
.zero 1<<32

Compiler avec gcc the_file.s -mcmodel=large -Wl,-fuse-ld=gold


5
1<<30est assez bon pour C. Puisqu'il s'agit d'un assembleur, la taille est en octets.
viraptor

2
@viraptor Mon système dispose de 32 Go de RAM et pour essayer, j'ai essayé de construire votre code. asparvient à passer à ld, mais ldéchoue avec cela . Pas même -mcmodel=mediumsemble aider.
Iwillnotexist Idonotexist

2
essayez de forcer l'utilisation de l' 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.
Lornix

2
J'ai finalement réussi à l'assembler sur Ubuntu 15.10 64 bits, avec invocation gcc -o g g.s -mcmodel=large -Wl,-fuse-ld=gold. Compte final:, 4,294,975,320 bytesavec 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).
Mego

3
En augmentant l'allocation jusqu'à 1<<33, je me suis retrouvé avec un 8,589,942,616exécutable d'octet.
Mego

60

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

struct indblock{
   uint32_t blocks[4096];
};

struct dindblock {
    struct indblock blocks[4096];
};

struct tindblock {
    struct dindblock blocks[4096];
};

struct inode {
    char data[52]; /* not bothering to retype the details */
    struct indblock ind;
    struct dindblock dint;
    struct tindblock tind;
};

struct inode bbtinode;

int main(){}

19
"Produirait un binaire de 16 To si vous aviez 16 To de RAM (ce n'est pas le cas)." - Je n'ai pas non plus de disque dur de 16 To! Je ne peux pas vraiment vérifier celui-ci, mais c'est quand même cool.
Dave

5
J'ai découvert celui-ci par accident et j'ai regardé le compilateur basculer lorsqu'il manquait d'espace d'adressage.
Josué

8
S'il vous plaît ne tentez pas de golf cette entrée; jouer au golf défait l'intention de l'exemple de code et il n'y a aucun avantage à le faire. Le code est déjà sous GPL depuis 2005.
Joshua

6
@BenVoigt Quoi qu'il en soit, éditer le code d'autres personnes n'est jamais acceptable ici. Laissez un commentaire s'il y a un problème. Meta
Mego

2
@Joshua: Vérifiez le diff diff. Mego n'a ajouté que la pointe de surbrillance.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

25

Pré-processeur en clair: entrée de 214 octets, sortie de 5 Mo

Inspiré par mon pré-processeur du monde réel, échouez ici .

#define A B+B+B+B+B+B+B+B+B+B
#define B C+C+C+C+C+C+C+C+C+C
#define C D+D+D+D+D+D+D+D+D+D
#define D E+E+E+E+E+E+E+E+E+E
#define E F+F+F+F+F+F+F+F+F+F
#define F x+x+x+x+x+x+x+x+x+x

int main(void) { int x, y = A; }

Les expériences montrent que chaque niveau de #defines (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».


9
C’est un peu comme une bombe XML
un oreillette

9
Plus précisément, il s’agit d’une implémentation du "Billion Laughs" original.
mınxomaτ

C'est fou mais simple.
Vahid Amiri

2
Wow, cela cause en fait une erreur de segmentation dans GCC 4.9 et Clang. Quel compilateur avez-vous utilisé?
Dave

1
@ Dave: Étrange. Lorsque je compile avec make, il compile, mais si je tape exactement la même commande que make, il se bloque. Et cela ne semble pas être lié aux variables d'environnement.
Thomas Padron-McCarthy

24

Java, source 450 + 22 = 472 octets, fichier de classe ~ 1 Go

B.java (version golfée, avertissement lors de la compilation)

import javax.annotation.processing.*;@SupportedAnnotationTypes("java.lang.Override")public class B extends AbstractProcessor{@Override public boolean process(java.util.Set a,RoundEnvironment r){if(a.size()>0){try(java.io.Writer w=processingEnv.getFiler().createSourceFile("C").openWriter()){w.write("class C{int ");for(int i=0;i<16380;++i){for(int j=0;j<65500;++j){w.write("i");}w.write(i+";int ");}w.write("i;}");}catch(Exception e){}}return true;}}

B.java (version non golfée)

import java.io.Writer;
import java.util.Set;

import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.annotation.processing.SupportedSourceVersion;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.TypeElement;

@SupportedAnnotationTypes("java.lang.Override")
@SupportedSourceVersion(SourceVersion.RELEASE_8)
public class B extends AbstractProcessor {
    @Override
    public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
        if (annotations.size() > 0) {
            try (Writer writer = processingEnv.getFiler().createSourceFile("C").openWriter()) {
                writer.write("class C{int ");
                for (int i = 0; i < 16380; ++i) {
                    for (int j = 0; j < 65500; ++j) {
                        writer.write("i");
                    }
                    writer.write(i + ";int ");
                }
                writer.write("i;}");
            } catch (Exception e) {
            }
        }
        return true;
    }
}

Compilation

javac B.java
javac -J-Xmx16G -processor B B.java

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 source C.javaet le compile C.classavec une taille en 1,073,141,162octets.

Il existe plusieurs limitations lorsqu’on essaie de créer un fichier de classe volumineux:

  • Création d' identifiants plus d'environ 64k résultats dans: error: UTF8 representation for string "iiiiiiiiiiiiiiiiiiii..." is too long for the constant pool.
  • La création de plus de 64 000 variables / fonctions entraîne: error: too many constants
  • Il existe également une limite d'environ 64 Ko pour la taille de code d'une fonction.
  • Il semble y avoir une limite générale (bug?) Dans le compilateur Java d'environ 1 Go pour le .classfichier. Si j'augmente 16380à 16390dans le code ci - dessus le compilateur ne retourne jamais.
  • Il existe également une limite d'environ 1 Go pour le .javafichier. L'augmentation 16380de 16400dans le code ci-dessus entraîne: An exception has occurred in the compiler (1.8.0_66). Please file a bug ...suivi de a java.lang.IllegalArgumentException.

10
Soigné; vous avez essentiellement créé votre propre préprocesseur, dans les limites de taille, dans un langage avec un compilateur prenant en charge de manière native les préprocesseurs personnalisés. C'est dans les règles. La classe finale n’était que de 0,5 Go pour moi, mais je peux confirmer la méthode.
Dave

Un autre exemple en Java habrahabr.ru/post/245333 - il utilise imbriqué 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)
Victor

J'ai remplacé le äpar un iet 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.
Sleafar

? étend TypeElement?!?
chat


22

C, source de 26 octets, sortie de 2.139.103.367 octets, programme valide

const main[255<<21]={195};

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 constsupprime l'indicateur d'écriture des pages du segment, de sorte que main peut être exécuté. Le 195est 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.


3
Il est intéressant de noter que la sortie est de 2 078 451 octets avec un taux de compression maximal = 1029: 1.
Zakipu

20

Boo , 71 octets. Temps de compilation: 9 minutes. 134 222 236 octet exécutable

macro R(e as int):
 for i in range(2**e):yield R.Body
x = 0
R 25:++x

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 sous bomb.booet appelez le compilateur avec booc bomb.boopour le construire.


2**e-Qu'est-ce que c'est? Essayez 9**e!
wchargin

1
@WChargin: Ce qui est amusant avec la métaprogrammation, c'est la facilité avec laquelle vous pouvez le personnaliser!
Mason Wheeler

J'ai un peu de mal à installer boo… Je confirmerai celui-ci quand je réussirai à l'installer!
Dave

@ Dave Quel problème as-tu avec?
Mason Wheeler

16

Kotlin , source 90 octets, 177416 octets (173 Ko) binaire compilé JVM

inline fun a(x:(Int)->Any){x(0);x(1)}
fun b()=a{a{a{a{a{a{a{a{a{a{a{println(it)}}}}}}}}}}}

Techniquement, vous pouvez prolonger cette durée en imbriquant davantage l'expression. Toutefois, le compilateur se bloque avec une StackOverflowerreur si vous augmentez la récursivité.


Vos préfixes SI ne sont pas d'accord. Est-ce que 177416 kilo-octets = 173 Mo ou 177416 octets = 173 Ko?
Ben Voigt le

1
@BenVoigt Merci de l'avoir signalé: D
TheNumberOne

Impressionnant, avoir un +1
J Atkin

Pour compiler Kotlin 1.2.20, nous devons supprimer une profondeur, ce qui correspond à environ 104 Ko. Quelle version avez-vous utilisé à l'origine?
TWiStErRob

15

C ++, 214 octets (aucune option de compilation spéciale n'est requise)

#define Z struct X
#define T template<int N
T,int M=N>Z;struct Y{static int f(){return 0;}};T>Z<N,0>:Y{};T>Z<0,N>:Y{};T,int M>Z{static int f(){static int x[99999]={X<N-1,M>::f()+X<N,M-1>::f()};}};int x=X<80>::f();

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-cygwinest 2567355421 octets (2,4 Go).

L'augmentation de la valeur initiale au-dessus de 80 divise l'assembleur cygwin gcc (trop de segments).

Aussi, 99999peut être remplacé par 9<<19ou 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à;)


Confirmé (en fait, c'est 2,56 Go avec clang), mais il a besoin d'un -cdrapeau 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.
Dave

@Dave: Les fichiers .o gcc sont au format ELF, n'est-ce pas?
Ben Voigt le

Pas certain. Ils ne commencent pas par un nombre magique ELF lorsque je les génère… j'examinerai plus tard.
Dave

@ Dave: Eh bien, cygwin gcc ne génère pas de fichier ELF. Linux gcc semble (bien que je regarde un code différent)
Ben Voigt

Oui, GCC 5.2.1 sur Kubuntu génère effectivement un fichier ELF, mais ce n’est que 9 Mo! Je ne sais pas comment il a réussi à le compresser autant par rapport aux autres compilateurs. Peut-être que GCC 4.9 créerait un fichier ELF de 2 Go.
Dave

6

Scala - source de 70 octets, résultat de 22980842 octets (après le pot)

import scala.{specialized => s}
class X[@s A, @s B, @s C, @s D, @s E]

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


Je ne pouvais pas le compiler: error: java.lang.OutOfMemoryError: GC overhead limit exceeded. Pourriez-vous également documenter la commande requise pour la compilation?
P.Péter

@ P.Péter - Vous devez donner plus de mémoire au compilateur, par exemple, scalac -J-Xmx12G X.scalac'est ce que j'ai utilisé. Je n'ai pas testé combien il a réellement besoin.
Rex Kerr

toujours pas compiler, malheureusement :( 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 foundPouvez-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.
P.Péter

Ubuntu 15.10, 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
Rex Kerr

2

C, 284 octets + 2 pour le -cin gcc bomb.c -o bomb.o -c; sortie: 2 147 484 052 octets

#define a 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
#define b a,a,a,a,a,a,a,a,a,a,a,a,a,a,a,a
#define c b,b,b,b,b,b,b,b,b,b,b,b,b,b,b,b
#define d c,c,c,c,c,c,c,c,c,c,c,c,c,c,c,c
#define e d,d,d,d,d,d,d,d,d,d,d,d,d,d,d,d
#define f e,e,e,e,e,e,e,e,e,e,e,e,e,e,e,e
__int128 x[]={f,f,f,f,f,f,f,f};

0

Boo, bien plus que ce que tu peux en attendre

macro R(e as int):for i in range(9**e):yield R.Body
x = 0
R 99:++x

Cela ressemble à la réponse de Mason Wheeler avec quelques petites modifications (??). Avez-vous obtenu la même réponse indépendamment ou y a-t-il quelque chose d'important dans les valeurs que vous avez modifiées (dans ce cas, éditez la réponse pour expliquer pourquoi elles sont importantes).
Dave

0

Python 3:

9**9**9**9**9

Bombe de pénétration


2
Vous devez indiquer le nombre d'octets de sortie pour voir comment votre entrée se compare aux autres.
Sanchises

Bienvenue chez PPCG! Il semble que vous ayez accidentellement créé deux comptes et posté cette réponse à deux reprises. J'ai enlevé l'autre réponse. Comme Sanchises l'a dit, ce défi est marqué par la taille du programme compilé . Vous devez donc inclure cette taille dans votre réponse car il s’agit du score principal. Notez également que le programme réel ne sera pas très volumineux, mais uniquement l'expression que vous créez en mémoire. Vous voudrez peut-être envisager une approche différente.
Martin Ender

1
@MartinEnder En raison de la façon dont Python évalue certaines expressions au moment de la compilation et stocke les nombres avec une précision arbitraire, cet exécutable (en théorie) sera plutôt volumineux. Mais comme l'a noté Aleksi Torhamo (qui a utilisé la même technique pour une partie de sa réponse), il a une limite autour de 2 Go, donc je m'attendrais à ce que ce code tel que rédigé ne compile probablement pas (bien que je n'ai pas vérifié ) Si l'OP peut le compiler et poste la taille compilée (avec la commande nécessaire pour le générer), il est alors valide. La similitude avec la réponse existante d'Aleksi me semble être une coïncidence.
Dave
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.