Побудуйте бомбу компілятора


372

Вступ

Напевно, ви знайомі з zip-бомбами , XML-бомбами тощо. Простіше кажучи, це (відносно) невеликі файли, які дають величезний вихід при інтерпретації наївного програмного забезпечення. Завдання тут полягає в зловживанні компілятором таким же чином.

Виклик

Напишіть деякий вихідний код, який займає 512 байт або менше і який компілюється у файл, який займає максимально можливий простір. Виграє найбільший вихідний файл!

Правила

Гаразд, тому є кілька важливих роз’яснень, визначень та обмежень;

  • Вихід компіляції повинен бути файлом ELF , портативним виконавчим файлом Windows (.exe) або віртуальним байт-кодом для JVM або CLR .Net (інші типи віртуальних байтових кодів також, ймовірно, будуть у порядку, якщо запитають). Оновлення: висновок .pyc / .pyo Python також враховується .
  • Якщо ваш вибір мови не може бути скомпільований безпосередньо в один із цих форматів, також дозволяється транспіляція, що супроводжується компіляцією ( Оновлення: ви зможете транспілювати кілька разів, до тих пір, поки ви ніколи не використовуєте одну й ту ж мову більше одного разу ).
  • Ваш вихідний код може складатися з декількох файлів і навіть файлів ресурсів, але підсумований розмір усіх цих файлів не повинен перевищувати 512 байт.
  • Ви не можете використовувати будь-який інший вхід, крім вихідних файлів і стандартної бібліотеки на ваш вибір мови. Статичне з'єднання стандартних бібліотек у порядку, коли воно підтримується. Зокрема, немає сторонніх бібліотек або бібліотек ОС.
  • Потрібно мати можливість викликати вашу компіляцію за допомогою команди або серії команд. Якщо під час компіляції вам потрібні конкретні прапори, вони зараховуються до вашого байтового ліміту (наприклад, якщо ваша лінія компіляції gcc bomb.c -o bomb -O3 -lm, -O3 -lmчастина (7 байт) буде зарахована (врахуйте, що початковий провідний простір не враховується).
  • Попередні процесори дозволені, лише якщо вони є стандартним варіантом компіляції для вашої мови.
  • Навколишнє середовище залежить від вас, але, щоб зробити це перевіреним, дотримуйтесь останніх (тобто доступних) версій компілятора та операційних систем (і, очевидно, вкажіть, яку ви використовуєте).
  • Він повинен компілюватися без помилок (попередження в порядку), а збій компілятора не рахується ні за що.
  • Те, що ваша програма насправді робить, не має значення, хоча це не може бути нічого шкідливого. Це навіть не повинно бути в старті.

Приклад 1

Програма С

main(){return 1;}

Скомпільовано Apple LLVM version 7.0.2 (clang-700.1.81)в ОС X 10.11 (64-розрядна):

clang bomb.c -o bomb -pg

Створює файл з 9228 байтів. Загальний розмір джерела становить 17 + 3 (для -pg) = 20 байт, що легко в межах граничного розміру.

Приклад 2

Програма Brainfuck:

++++++[->++++++++++++<]>.----[--<+++>]<-.+++++++..+++.[--->+<]>-----.--
-[-<+++>]<.---[--->++++<]>-.+++.------.--------.-[---<+>]<.[--->+<]>-.

Транспільовано з wiib на c:

./awib < bomb.bf > bomb.c

Потім компілюється з Apple LLVM version 7.0.2 (clang-700.1.81)ОС X 10.11 (64-розрядна):

clang bomb.c

Створює файл з 8464 байтів. Загальний вхід тут становить 143 байти (оскільки @lang_cце типово для awib, його не потрібно було додавати у вихідний файл, і жодної команди немає спеціальних прапорів).

Також зауважте, що в цьому випадку тимчасовий файл bomb.c становить 802 байти, але це не враховує ні розмір джерела, ні розмір виводу.

Заключна примітка

Якщо буде досягнуто вихід більше 4 Гб (можливо, якщо хтось знайде цілісного препроцесора), конкуренція буде за найменший джерело, який створює файл принаймні такого розміру (це просто не практично для тестування матеріалів, які стають занадто великими) .


Якщо ви використовуєте транспілятор, чи повинен вихідний вихідний код містити менше 512 байт, а також вихідний вихідний код?
трихоплакс

3
Чи допускається повторна транспіляція?
orlp

3
@ LegionMammal978 так, він повинен створити один із вказаних я типів файлів. Але якщо ви думаєте, що ви знайшли щось, що є віртуальнішою машиною, ніж інтерпретована мова, запитайте про це конкретно, і можливо, я дозволю це (це трохи суб'єктивно, тому я хотів бути дуже обмежуючим для початку, з опцією його відкриття)
Дейв

3
@trichoplax я цього не знав, але з деяких читань це виглядає так. компіляція в байт-код Python абсолютно зараховується. Отже, для python розмір виводу буде загальним розміром всіх ваших файлів pyc / pyo. Незабаром я оновлю питання з цими оновленнями на основі коментарів.
Дейв

2
@MartinRosenau - WGroleau вже задав подібне запитання; це стандартне завдання в кодуванні, що ви можете використовувати все, що існувало, коли виклик почався.
Дейв

Відповіді:


441

C, (14 + 15) = 29 байт-джерело, 17,179,875,837 (16 ГБ) байт, що виконується

Дякуємо @viraptor за 6 байт.

Завдяки @hvd за 2 байти та виконуваний розмір x4.

Це визначає mainфункцію як великий масив та ініціалізує її перший елемент. Це змушує GCC зберігати весь масив у отриманому виконаному файлі.

Оскільки цей масив більший за 2 Гб, нам потрібно надати -mcmodel=mediumпрапор GCC. Додаткові 15 байт включені в рахунок, згідно з правилами.

main[-1u]={1};

Не сподівайтеся, що цей код не буде нічого приємного під час запуску.

Зібрати:

gcc -mcmodel=medium cbomb.c -o cbomb

Мені знадобилося певний час, щоб перейти до тестування пропозиції @ hvd - і знайти машину з достатньою кількістю соку для роботи. Врешті-решт я знайшов старий невиробничий RedHat 5.6 VM з 10 Гб оперативної пам’яті, свопом 12 ГБ та / tmp, встановленим на великій локальній частині. Версія GCC - 4.1.2. Загальний час складання близько 27 хвилин.

Завдяки завантаженню процесора та оперативної пам’яті, я рекомендую не робити цю компіляцію на будь-якій віддаленій виробництві машині .



13
Тут я граю проти свого рішення, але ... вам не потрібно a. Можна просто скористатисяmain[1<<30]={1};
viraptor

38
О Боже. Це зло. X замерз на кілька хвилин, намагаючись скласти цей код. Я починав шукати інший комп’ютер, щоб, можливо, ввійти назад і вбити процес gcc, перш ніж він нарешті ожив. Btw. Якщо ви хочете більше значення, ніж 1<<30тоді, це 7<<28може бути варіант.
kasperd

33
> 4 Гб? Це швидко наростало
Уейн Вернер

18
Якщо хтось цікавиться, чому це складається: stackoverflow.com/questions/34764796/…
ТК

206

C #, близько 1 хв на компіляцію, 28MB вихідний двійковий:

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

Якщо додати більше Y, це збільшить розмір в експоненціальному масштабі.

Пояснення Pharap згідно запиту @Odomontois:

Ця відповідь зловживає параметрами успадкування та типу для створення рекурсії. Щоб зрозуміти, що відбувається, простіше спочатку спростити проблему. Поміркуйте class X<A> { class Y : X<Y> { Y y; } }, що породжує родовий клас X<A>, який має внутрішній клас Y. X<A>.Yуспадковує X<Y>, отже, X<A>.Yтакож є внутрішній клас Y, який є тоді X<A>.Y.Y. Тоді також є внутрішній клас Y, і цей внутрішній клас Yмає внутрішній клас Yтощо. Це означає, що ви можете використовувати роздільну здатність ( .) ad infinitum, і кожен раз, коли ви використовуєте, компілятор повинен виводити інший рівень спадкування та параметризацію типу .

Додаючи додаткові параметри типу, робота, яку повинен виконувати компілятор на кожному етапі, ще більше збільшується.

Розглянемо наступні випадки:
В class X<A> { class Y : X<Y> { Y y;} }типу парам Aмає тип X<A>.Y.
В class X<A> { class Y : X<Y> { Y.Y y;} }типу парах Aмають тип X<X<A>.Y>.Y.
В class X<A> { class Y : X<Y> { Y.Y.Y y;} }типу парах Aмають тип X<X<X<A>.Y>.Y>.Y.
У class X<A,B> { class Y : X<Y,Y> { Y y;} }типі пари Aце X<A,B>.Yі Bє X<A,B>.Y.
У class X<A> { class Y : X<Y> { Y.Y y;} }типі пари Aце X<X<A,B>.Y, X<A,B>.Y>.Yі Bє X<X<A,B>.Y, X<A,B>.Y>.Y.
У class X<A> { class Y : X<Y> { Y.Y.Y y;} }типі пари Aце X<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Yі Bє X<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Y.

Дотримуючись цієї закономірності, можна лише уявити собі 1 роботу, яку повинен був зробити компілятор, щоб зробити висновок про те, Aу чому Eполягає Y.Y.Y.Y.Y.Y.Y.Y.Yвизначення 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 Ви могли це зрозуміти, але вам знадобиться багато терпіння, і інтелігенція тут вам не допоможе.


14
Це більше схоже на такий тип божевілля, якого я очікував! Схоже, я збираюся перевстановити Mono…
Дейв,

31
Чи можете ви надати пояснення такого горезвісного ефекту?
Одонмонтуа

16
+1 - робити більше, ніж просто ініціалізувати великий масив.
Stig Hemmer

6
Ось приклад використання Try Roslyn та лише 3 Yс .
Кобі

10
Я побачив це питання і одразу подумав про тебе. Приємно!
Ерік Ліпперт

154

Python 3, 13-байтне джерело, 9,057,900,463 байт (8,5GiB) .pyc-файл

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

Редагувати : Змінив код на версію вище, після того як я зрозумів, що правило, розмір виходу понад 4GiB не має значення, і код для цього стає настільки трохи коротшим; Попередній код - а ще важливіше пояснення - можна знайти нижче.


Python 3, 16-байтне джерело,> 32TB .pyc-файл (якщо у вас достатньо пам'яті, місця на диску та терпіння)

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

Пояснення: Python 3 робить постійне складання, і ви отримуєте великі числа швидко з експоненцією. Формат, використовуваний у файлах .pyc, зберігає довжину цілого представлення, використовуючи 4 байти, але насправді ліміт здається більше схожим 2**31, тому, використовуючи просто експоненцію для створення одного великого числа, ліміт, здається, генерує 2 Гб. файл pyc із 8-байтного джерела. ( 19**8трохи сором’язливий 8*2**31, тому 1<<19**8має двійкове представлення трохи менше 2 Гб; множення на вісім - це тому, що ми хочемо байти, а не біти)

Однак кортежі також непорушні, і примноження кортежу також постійно складне, тому ми можемо дублювати цю крапку 2 ГБ стільки разів, скільки нам хочеться, принаймні, хоча б 2**31раз. 4**7, Щоб дістатися до 32 Тб був обраний тільки тому , що це був перший показник я міг би знайти , що побити попередній 16TB відповідь.

На жаль, маючи пам'ять, яку я маю на власному комп’ютері, я міг би перевірити це лише до множника 2, тобто. (1<<19**8,)*2, який створив файл 8,5 ГБ, що, сподіваюся, демонструє, що відповідь реальна (тобто розмір файлу не обмежений 2 ** 32 = 4 ГБ).

Крім того, я не маю уявлення, чому розмір файлу, який я отримав під час тестування, становив 8,5 ГБ замість очікуваного 4 ГБ, і файл досить великий, що в даний момент я не відчуваю, як тикатися навколо нього.


2
+1, але чому б ні (1<<19**8,)*2? 4 ГБ достатньо.
Акангка

2
@ChristianIrwan: Так, я забув це правило, зрозумів це лише кілька хвилин тому і не зрозумів, яку редакцію я повинен зробити ще. :-)
Алексі Торхамо

1
Приємно. Оскільки це всього 13 байтів, ми нарешті є претендентом на відповідь, що розміщена вперше! Мені вдалося підтвердити лише 1<<18на своїй машині (1,5 ГБ), але я протестую його на Linux, пізніше, де, сподіваюся, він буде працювати з повними 8 ГБ (не збираюся пробувати версію 32 ТБ!)
Дейв

1
@Dave: Точний розмір може залежати від версії (все-таки 1,5 Гб звучить дивно, хоч би що); Я використовував Python 3.3.5 і використовував python -m py_compile asd.pyдля створення .pyc-файлу.
Алексі Торхамо

3
IIRC, python використовує 30 біт на 32-бітове слово в цілочисленному поданні

130

Якщо буде досягнуто вихід більше 4 Гб (можливо, якщо хтось знайде цілісного препроцесора), конкуренція буде за найменший джерело, який створює файл принаймні такого розміру (це просто не практично для тестування матеріалів, які стають занадто великими) .

"Шаблон Haskell" дозволяє генерувати код Haskell під час компіляції за допомогою Haskell, і, отже, є повноцінним попереднім процесором.

Ось моя спроба, параметризована довільним числовим виразом FOO:

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

Магія - це код всередині "сплайса" $(...). Це буде виконано під час компіляції, щоб генерувати Haskell AST, який прищеплюється до AST програми замість сплайса.

У цьому випадку ми робимо простий AST, що представляє буквальний 0, повторюємо цей FOOраз, щоб скласти список, потім використовуємо ListEз Language.Haskell.THмодуля перетворення цього списку AST в один великий AST, що представляє буквальне [0, 0, 0, 0, 0, ...].

В результаті програма еквівалентна main = print [0, 0, 0, ...]з FOOповтореннями 0.

Для компіляції в 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

Він важить в 83 байти (66 для коду Haskell і 17 для -XTemplateHaskellаргументу) плюс довжина FOO.

Ми можемо уникнути аргументу компілятора і просто компілювати ghc, але ми маємо поставити його {-# LANGUAGE TemplateHaskell#-}на початку, що стикає код до 97 байт.

Ось кілька прикладів виразів FOOта розміру отриманого двійкового файлу:

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

У мене закінчилася оперативна пам’ять (2^20).

Ми також можемо створити нескінченний список, використовуючи repeatзамість цього replicate FOO, але це заважає компілятору зупинятися;)


46
Ласкаво просимо до головоломки програмування та коду для гольфу. Це яскрава відповідь, особливо для нового користувача цього сайту. Якщо вам потрібна допомога (в чому я сумніваюся), сміливо запитайте.
wizzwizz4

3
@ wizzwizz4: Так, це геніальна відповідь. Це по суті те саме, що і моє, за винятком того, що в Haskell для роботи метапрограмування потрібна спеціальна директива компілятора. ;)
Мейсон Уілер

2
Коли я компілюю з GHC 7.8.3, я отримую "Не в області дії: '<$>'" (я встановлюю код [...].replicate (2^10)<$>[|0|])). Я не маю досвіду з Haskell; якісь підказки про те, як зробити цю компіляцію?
Дейв

38
Занадто поганий haskell шаблону не лінивий, щоб виводити нескінченний виконуваний файл.
PyRulez

1
Привіт @Dave <$>функція широко використовується в Haskell, але вона була переміщена лише до "прелюдії" (набору функцій, доступних за замовчуванням) у GHC 7.10. Для більш ранніх версій вам потрібно буде додати import Control.Applicative;після існуючого importоператора. Я просто спробував з GHC 7.8.4, і він працює.
Варбо

80

C ++, 250 + 26 = 276 байт

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;

Це функція Ackermann, реалізована в шаблонах. Я не в змозі компілювати h=a<4,2>::n;на моїй маленькій машині (6 Гб), але мені вдалося h=a<3,14>отримати вихідний файл 26 М. Ви можете налаштувати константи, щоб досягти меж вашої платформи - для ознайомлення дивіться пов'язану статтю у Вікіпедії.

Потрібен -gпрапор GCC (оскільки всі символи налагодження фактично займають будь-який простір), і більша глибина шаблону, ніж за замовчуванням. Мій рядок компіляції закінчився як

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

Інформація про платформу

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

Мені це дуже подобається, але я не впевнений, що можу прийняти вихід .o, оскільки я сказав ELF / .exe / тощо. (і компіляція цього повністю оптимізує все це!). Все-таки +1 (і підтверджено)
Дейв

4
Оновлення: Як Бен Фойгт вказує на його відповідь, GCC на Linux робить генерувати ELF файли як .o вихід, і я був в змозі підтвердити варіант <3,14> з ним, так що так - це вірно.
Дейв

17
Я очікував, що з шаблонів C ++ вийде щось абсурдне. Я не сподівався на функцію Акермана.
Марк

чи не дасть Фібоначчі менший код та кращий контроль розміру виводу?
Чи буде Несс

1
Але ми хочемо більшого коду! Фібоначчі надає майже такий же розмір, як чистий лінійний код (але довший час компіляції, ніж лінійний). Ви, звичайно, могли б розважитися статичним масивом розмірів A+Bу кожному класі, тепер я думаю про це ...
Toby Speight

65

ASM, 61 байт (29 байтів, 32 байти для прапорів), 4,294,975,320 байт

.globl main
main:
.zero 1<<32

Компілювати з gcc the_file.s -mcmodel=large -Wl,-fuse-ld=gold


5
1<<30досить хороший для C. Оскільки це асемблер, розмір знаходиться в байтах.
viraptor

2
@viraptor У моїй системі є 32 ГБ оперативної пам’яті, і для ударів я намагався створити ваш код. asвдається передати від ld, але ldНЕ може з цим . Навіть, -mcmodel=mediumздається, не допомагає.
Iwillnotexist Idonotexist

2
спробуйте примусити використовувати goldлінкер: gcc -fuse-ld=gold ...компілює / посилає ... eek! Закінчено за 1:29 (89 секунд) і розміром 1,073,748 000 байт.
lornix

2
Нарешті я отримав це для збирання на 64-розрядному Ubuntu 15.10, з викликом gcc -o g g.s -mcmodel=large -Wl,-fuse-ld=gold. Підсумковий підсумок: 4,294,975,320 bytesз 32 додатковими байтами додано до довжини програми для -mcmodel=large -Wl,-fuse-ld=gold. Варто зазначити, що заголовок неправильний; джерело - 29 байт (без додаткових прапорців).
Mego

3
Збиваючи розподіл до 1<<33, я закінчився виконанням 8,589,942,616байтів.
Mego

60

Ось мій відповідь на C від 2005 року. Коли б у вас була 16 ТБ оперативної пам’яті (ви цього не зробите), ви отримаєте двійковий файл розміром 16 ТБ.

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
"Виробляли б бінарний модуль 16 ТБ, якби у вас була оперативна пам'ять 16 ТБ (ви цього не робите)." - ні в мене немає жорсткого диска 16 ТБ! Я не можу реально перевірити це, але все-таки це круто.
Дейв

5
Я виявив це випадково і спостерігав, як компілятор перевалюється, коли у нього не вистачає адресного простору.
Джошуа

8
Будь ласка, НЕ намагайтеся пограти в цей гольф; гольф перемагає наміри кодового зразка, і жодних переваг для цього в жодному разі немає. Код вже GPL'd станом на 2005 рік.
Джошуа

6
@BenVoigt Незважаючи на те, редагування чужого коду тут ніколи не прийнятно. Залиште коментар, якщо є проблема. Відповідна мета-повідомлення: meta.codegolf.stackexchange.com/questions/1615/…
Mego

2
@Joshua: Перевірте відмітку розл. Мего лише додав підказки підкреслення.
n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳

25

Простий старий препроцесор C: вхід 214 байт, вихід 5 Мб

Натхненний мій реальний препроцесор невдача тут .

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

Експерименти показують, що кожен рівень #defines (як очікується) зробить вихід приблизно в десять разів більшим. Але оскільки на цей приклад пішло більше години на складання, я ніколи не переходив до "G".


9
Це щось на зразок xml бомби
вушну візку

9
Зокрема, це реалізація оригіналу "Мільярд сміху".
mınxomaτ

Це божевільно, але просто.
Вахід Амірі

2
Нічого так, це насправді викликає сегментацію в GCC 4.9 та Clang. Який компілятор ви використовували?
Дейв

1
@Dave: Дивно. Коли я компілюю за допомогою make, він компілюється, але якщо я набираю точно таку ж команду, яка використовує, вона виходить з ладу. І, схоже, це не пов’язано зі змінними середовища.
Томас Падрон-Маккарті

24

Java, 450 + 22 = 472 байт джерело, ~ клас 1 ГБ класу

B.java (версія для гольфу, попередження під час компіляції)

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 (неліфована версія)

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

Компіляція

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

Пояснення

Ця бомба використовує процесори анотацій. Для цього потрібно 2 проходи для компіляції. Перший прохід будує клас процесорів B. Під час другого проходу процесор створює новий вихідний файл C.javaі компілює його до а C.classз розміром 1,073,141,162байтів.

При спробі створити файл великого класу є кілька обмежень:

  • Створення ідентифікаторів більше , ніж близько 64k результатів: error: UTF8 representation for string "iiiiiiiiiiiiiiiiiiii..." is too long for the constant pool.
  • Створення більш ніж приблизно 64 к змінних / функцій призводить до: error: too many constants
  • Існує також обмеження приблизно 64 к для розміру коду функції.
  • Здається, загальний ліміт (помилка?) У компіляторі Java близько 1 Гб для .classфайлу. Якщо я збільшую 16380до16390 вищевказаного коду, компілятор ніколи не повертається.
  • Також для .javaфайлу обмежено близько 1 ГБ . Збільшення 16380до 16400вищевказаного коду призводить до: з An exception has occurred in the compiler (1.8.0_66). Please file a bug ...наступним a java.lang.IllegalArgumentException.

10
Акуратний; Ви по суті створили власного препроцесора, в межах обмеження, мовою з компілятором, який в основному підтримує спеціальні препроцесори. Це в межах правил. Підсумковий клас для мене склав лише 0,5 ГБ, але я можу підтвердити метод.
Дейв

Ще один приклад Java habrahabr.ru/post/245333 - він використовує вкладені try..finally(код у остаточному блоці дублюється для звичайних та виняткових випадків) та блок ініціалізатора (код із блоку ініціалізатора додається до кожного конструктора)
Віктор

Я замінив ä на iі скорегував цифри. Тепер бомба повинна створити клас 1 ГБ в будь-якій системі без проблем кодування. Однак зараз їй потрібно набагато більше пам’яті.
Sleafar

? розширює TypeElement?!?
кіт


22

C, 26 байт-джерело, 2,139,103,367 байт, дійсна програма

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

Складено за допомогою: gcc cbomb.c -o cbomb(gcc версія 4.6.3, Ubuntu 12.04, ~ 77 секунд)

Я думав, що спробую побачити, наскільки великим я можу зробити дійсну програму, не використовуючи жодних параметрів командного рядка. Я отримав ідею з цієї відповіді: https://codegolf.stackexchange.com/a/69193/44946 від Digital Trauma. Дивіться коментарі до того, чому це складається.

Як це працює: constВидаляє прапор запису зі сторінок у сегменті, тому головне може бути виконане. Це 195машинний код Intel для повернення. А оскільки архітектура Intel мало ендіастична, це перший байт. Програма вийде з будь-якого стартового коду, що міститься в реєстрі eax, ймовірно, 0.

Це лише близько 2 гігів, оскільки лінкер використовує 32-бітові підписані значення для компенсацій. Це на 8 мег менше, ніж 2 гіги, тому що компілятору / лінкеру потрібен простір для роботи, і це найбільший, який я міг би отримати без помилок лінкера - ymmv.


3
Як цікавий бік, вихід 2,078,451 байт gziped з максимальним стисненням = 1029: 1 коефіцієнт стиснення.
Закіпу

20

Бу , 71 байт. Час компіляції: 9 хвилин. 134,222,236 байт у виконанні

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

Використовує макрос R(для Repeat), щоб змусити компілятор множити оператор приросту довільну кількість разів. Не потрібні спеціальні прапори компілятора; просто збережіть файл як bomb.booі викликайте компілятор, booc bomb.booщоб створити його.


2**e-що це? Спробуйте 9**e!
wchargin

1
@WChargin: Найцікавіша метапрограмування - це те, наскільки легко ви можете налаштувати її!
Мейсон Уілер

У мене є проблеми з установкою boo ... Я підтверджую це, коли мені вдасться його встановити!
Дейв

@Dave Які проблеми з цим виникають?
Мейсон Уілер

16

Котлін , джерело 90 байт, 177416 байт (173 КБ) склав двійковий файл 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)}}}}}}}}}}}

Технічно ви можете зробити це ще довше, вклавши вираз далі. Однак компілятор виходить з ладу, StackOverflowякщо ви збільшуєте рекурсію.


Ваші префікси SI не згодні. Це 177416 кілобайт = 173 Мбайт, або 177416 байт = 173 кБ?
Ben Voigt

1
@BenVoigt Дякую, що вказали на це: D
TheNumberOne

Вражаючий, майте +1
J Atkin

Для компіляції Kotlin 1.2.20 нам потрібно видалити одну глибину, і це ~ 104 кБ. Яку версію ви використовували спочатку?
TWiStErRob

15

C ++, 214 байт (не потрібні спеціальні параметри компіляції)

#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();

Це досить проста двовимірна рекурсія шаблону (глибина рекурсії йде як квадратний корінь загальних випромінюваних шаблонів, тому не перевищує межі платформи), з невеликою кількістю статичних даних у кожному.

Створений об’єктний файл із g++ 4.9.3 x86_64-pc-cygwin 2567355421 байтами (2,4 ГбіБ).

Збільшення початкового значення вище 80 розбиває асемблер cygwin gcc (занадто багато сегментів).

Крім того, 99999можна замінити 9<<19або подібним для збільшення розміру, не змінюючи вихідний код ... але я не думаю, що мені потрібно використовувати більше дискового простору, ніж я вже є;)


Підтверджено (насправді це 2,56 Гб з клангом), але йому потрібен -cпрапор компіляції, щоб зупинити лінкер (2 зайві байти), і я не впевнений, що можу прийняти .o вихід (не один із тих, кого я перерахував). Все-таки мені це подобається, тому +1.
Дейв

@Dave: gcc .o файли у форматі ELF, чи не так?
Бен Войт

Не впевнений. Вони не починаються з магічного числа ELF, коли я їх генерую… Я вивчу пізніше.
Дейв

@Dave: Ну, cygwin gcc не генерує файл ELF. Linux gcc, здається, (хоча я дивлюся на один із іншого фрагмента коду)
Ben Voigt

Так, GCC 5.2.1 на Kubuntu справді генерує файл ELF, але це лише 9 Мб! Не впевнений, як вдалося його так сильно стиснути порівняно з іншими компіляторами. Можливо, GCC 4.9 створив би файл 2 ГБ ELF.
Дейв

6

Scala - 70 байт, 22980842 байт результат (після баночки)

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

Це дає 9 5 (близько 59 000) файлів спеціалізованого класу, які упаковуються в банку розміром близько 23 Мб. В принципі, ви можете продовжувати роботу, якщо у вас є файлова система, яка може обробляти стільки файлів і достатньо пам'яті.

(Якщо потрібно включити команду jar, це 82 байти.)


Я не міг скомпілювати: error: java.lang.OutOfMemoryError: GC overhead limit exceeded. Чи можете ви також документувати необхідну команду для компіляції?
П.Петер

@ P.Péter - Вам потрібно надати компілятору більше пам’яті, наприклад, scalac -J-Xmx12G X.scalaце я використовував. Я не перевіряв, наскільки це насправді потрібно.
Рекс Керр

все ще не компілюється, на жаль :( 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Чи можете ви вказати версію scala та java (можливо, і платформу)? Я використовував scalac 2.9.2 та OpenJDK 1.8.0_66-Internal-b17, на 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 Керр

2

C, 284 байт + 2 для -cвходу gcc bomb.c -o bomb.o -c; вихід: 2 147 484 052 байт

#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

Бу, набагато більше, ніж можна від цього очікувати

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

Це виглядає як відповідь Мейсона Уілера з кількома невеликими змінами (??). Ви дійшли до тієї самої відповіді самостійно чи є щось важливе у змінених значеннях (якщо так, будь ласка, відредагуйте відповідь, щоб пояснити, чому вони важливі).
Дейв

0

Пітон 3:

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

Тетраційна бомба


2
Ви повинні вказати, скільки байтів є вихід, щоб побачити, як ваш запис порівнюється з іншими.
Санчіз

Ласкаво просимо до PPCG! Здається, ви випадково створили два облікові записи та двічі опублікували цю відповідь. Я видалив іншу відповідь. Як сказав Санчіз, цей виклик визначається розміром складеної програми . Отже, ви повинні включити цей розмір у свою відповідь, оскільки це основний бал. Також зауважте, що фактична програма не буде дуже великою, а лише вираз, який ви створюєте в пам'яті, тож ви можете подумати про інший підхід.
Мартін Ендер

1
@MartinEnder завдяки тому, як Python оцінює деякі вирази під час компіляції та зберігає числа у довільній точності, це (теоретично) матиме досить великий виконуваний файл. Але, як зазначав Алексі Торхамо (який використовував ту саму техніку для частини своєї відповіді), це обмеження десь близько 2 Гб, тому я б очікував, що цей код, як написано, ймовірно, не буде компілюватися (хоча я не перевіряв ). Якщо ОП може змусити його складати і розміщувати зібраний розмір (разом з командою, необхідною для його створення), то це дійсно. Подібність до існуючої відповіді Алексі для мене виглядає як збіг.
Дейв
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.