pengantar
Anda mungkin akrab dengan bom ritsleting , bom XML , dll. Sederhananya, mereka adalah (relatif) file kecil yang menghasilkan output yang sangat besar ketika ditafsirkan oleh perangkat lunak naif. Tantangannya di sini adalah menyalahgunakan kompiler dengan cara yang sama.
Tantangan
Tulis beberapa kode sumber yang menempati 512 byte atau kurang dan yang dikompilasi menjadi file yang menempati ruang paling mungkin. File output terbesar menang!
Aturan
OK, jadi ada beberapa klarifikasi, definisi, dan batasan penting;
- Output dari kompilasi harus berupa file ELF , Windows Portable Executable (.exe), atau bytecode virtual untuk JVM atau .Net's CLR (jenis bytecode virtual lain juga cenderung OK jika diminta). Pembaruan: Output .pyc / .pyo Python juga diperhitungkan .
- Jika bahasa pilihan Anda tidak dapat dikompilasi secara langsung ke dalam salah satu format tersebut, transpilasi diikuti oleh kompilasi juga diperbolehkan ( Perbarui: Anda dapat mentranspilasikan beberapa kali, asalkan Anda tidak pernah menggunakan bahasa yang sama lebih dari sekali ).
- Kode sumber Anda dapat terdiri dari beberapa file, dan bahkan file sumber daya, tetapi ukuran total semua file ini tidak boleh melebihi 512 byte.
- Anda tidak dapat menggunakan input selain dari file sumber Anda dan perpustakaan standar bahasa pilihan Anda. Menghubungkan statis perpustakaan standar adalah OK jika didukung. Secara khusus, tidak ada perpustakaan pihak ketiga atau perpustakaan OS.
- Harus dimungkinkan untuk menjalankan kompilasi Anda menggunakan perintah atau serangkaian perintah. Jika Anda memerlukan tanda tertentu saat dikompilasi, ini dihitung menuju batas byte Anda (mis. Jika garis kompilasi Anda
gcc bomb.c -o bomb -O3 -lm
,-O3 -lm
bagian (7 byte) akan dihitung (perhatikan ruang awal awal tidak dihitung). - Pra-prosesor hanya diizinkan jika mereka merupakan opsi kompilasi standar untuk bahasa Anda.
- Lingkungan terserah pada Anda, tetapi demi kepentingan membuat hal ini dapat diverifikasi, patuhi versi kompiler dan sistem operasi terbaru (yaitu yang tersedia) (dan jelas tentukan yang Anda gunakan).
- Itu harus dikompilasi tanpa kesalahan (peringatan OK), dan menabrak kompiler tidak menghitung apa pun.
- Apa yang sebenarnya dilakukan oleh program Anda tidak relevan, meskipun tidak bisa berupa apa pun yang berbahaya. Bahkan tidak harus bisa memulai.
Contoh 1
Program C.
main(){return 1;}
Dikompilasi dengan Apple LLVM version 7.0.2 (clang-700.1.81)
pada OS X 10.11 (64-bit):
clang bomb.c -o bomb -pg
Menghasilkan file sebesar 9228 byte. Ukuran sumber total adalah 17 + 3 (untuk -pg
) = 20 byte, yang mudah dalam batas ukuran.
Contoh 2
Program Brainfuck:
++++++[->++++++++++++<]>.----[--<+++>]<-.+++++++..+++.[--->+<]>-----.--
-[-<+++>]<.---[--->++++<]>-.+++.------.--------.-[---<+>]<.[--->+<]>-.
Diubah dengan awib ke c dengan:
./awib < bomb.bf > bomb.c
Kemudian dikompilasi dengan Apple LLVM version 7.0.2 (clang-700.1.81)
pada OS X 10.11 (64-bit):
clang bomb.c
Menghasilkan file 8464 byte. Input total di sini adalah 143 byte (karena @lang_c
merupakan default untuk awib, ia tidak perlu ditambahkan ke file sumber, dan tidak ada flag khusus pada kedua perintah).
Juga perhatikan bahwa dalam kasus ini, file bomb.c sementara adalah 802 byte, tetapi ini tidak memperhitungkan ukuran sumber maupun ukuran output.
Catatan Akhir
Jika output lebih dari 4GB tercapai (mungkin jika seseorang menemukan preprocessor lengkap turing), kompetisi akan menjadi sumber terkecil yang menghasilkan file sekurang-kurangnya sebesar itu (tidak praktis untuk menguji pengiriman yang terlalu besar) .
Jawaban:
C, (14 + 15) = 29 byte sumber, 17.179.875.837 (16 GB) byte dieksekusi
Berkat @viraptor untuk 6 byte.
Berkat @hvd untuk 2 byte dan ukuran x4 yang dapat dieksekusi.
Ini mendefinisikan
main
fungsi sebagai array besar dan menginisialisasi elemen pertamanya. Ini menyebabkan GCC untuk menyimpan seluruh array di executable yang dihasilkan.Karena array ini lebih besar dari 2GB, kami perlu menyediakan
-mcmodel=medium
flag ke GCC. 15 byte tambahan termasuk dalam skor, sesuai aturan.Jangan berharap kode ini melakukan hal yang baik saat dijalankan.
Kompilasi dengan:
Butuh beberapa saat untuk memeriksa saran @ hvd - dan menemukan mesin dengan jus yang cukup untuk menanganinya. Akhirnya saya menemukan RedHat 5.6 VM non-produksi lama dengan 10GB RAM, 12GB swap, dan / tmp diatur ke partisi lokal besar. Versi GCC adalah 4.1.2. Total waktu kompilasi sekitar 27 menit.
sumber
a
. Anda bisa menggunakanmain[1<<30]={1};
1<<30
maka7<<28
bisa menjadi pilihan.C #, sekitar 1 menit untuk dikompilasi, biner keluaran 28MB:
Menambahkan lebih banyak Y akan meningkatkan ukuran secara eksponensial.
Penjelasan oleh Pharap sesuai permintaan @Odomontois:
Jawaban ini menyalahgunakan pewarisan dan ketik parameter untuk membuat rekursi. Untuk memahami apa yang terjadi, lebih mudah untuk menyederhanakan masalah terlebih dahulu. Pertimbangkan
class X<A> { class Y : X<Y> { Y y; } }
, yang menghasilkan kelas generikX<A>
, yang memiliki kelas dalamY
.X<A>.Y
mewarisiX<Y>
, karenanyaX<A>.Y
juga memiliki kelas batinY
, yang kemudianX<A>.Y.Y
. Ini kemudian juga memiliki kelas dalamY
, dan bahwa kelas dalamY
memiliki kelas dalamY
dll. Ini berarti bahwa Anda dapat menggunakan resolusi lingkup (.
) tanpa batas, dan setiap kali Anda menggunakannya, kompiler harus menyimpulkan tingkat pewarisan dan jenis parameterisasi lainnya .Dengan menambahkan parameter tipe tambahan, pekerjaan yang harus dilakukan oleh kompiler pada setiap tahap semakin meningkat.
Pertimbangkan kasus-kasus berikut:
Dalam
class X<A> { class Y : X<Y> { Y y;} }
tipe paramA
memiliki tipeX<A>.Y
.Dalam
class X<A> { class Y : X<Y> { Y.Y y;} }
tipe paramA
memiliki tipeX<X<A>.Y>.Y
.Dalam
class X<A> { class Y : X<Y> { Y.Y.Y y;} }
tipe paramA
memiliki tipeX<X<X<A>.Y>.Y>.Y
.Dalam
class X<A,B> { class Y : X<Y,Y> { Y y;} }
jenis paramA
adalahX<A,B>.Y
danB
adalahX<A,B>.Y
.Dalam
class X<A> { class Y : X<Y> { Y.Y y;} }
jenis paramA
adalahX<X<A,B>.Y, X<A,B>.Y>.Y
danB
adalahX<X<A,B>.Y, X<A,B>.Y>.Y
.Dalam
class X<A> { class Y : X<Y> { Y.Y.Y y;} }
jenis paramA
adalahX<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Y
danB
adalahX<X<X<A,B>.Y, X<A,B>.Y>.Y, X<X<A,B>.Y, X<A,B>.Y>.Y>.Y
.Mengikuti pola ini, satu hanya dapat membayangkan 1 pekerjaan compiler harus lakukan untuk menyimpulkan apa
A
yangE
berada diY.Y.Y.Y.Y.Y.Y.Y.Y
dalam definisiclass 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 Anda bisa mengetahuinya, tetapi Anda perlu banyak kesabaran, dan kecerdasan tidak akan membantu Anda di sini.
sumber
Y
detik .Python 3, sumber 13 byte, 9.057.900.463 byte (8,5GiB) .pyc-file
Sunting : Mengubah kode ke versi di atas setelah saya menyadari aturan mengatakan ukuran output di luar 4GiB tidak masalah, dan kode untuk yang ini sedikit lebih pendek; Kode sebelumnya - dan yang lebih penting penjelasannya - dapat ditemukan di bawah.
Python 3, 16 byte source,> 32TB .pyc-file (jika Anda memiliki cukup memori, ruang disk, dan kesabaran)
Penjelasan: Python 3 melakukan pelipatan konstan, dan Anda mendapatkan angka besar cepat dengan eksponen. Format yang digunakan oleh file .pyc menyimpan panjang representasi integer menggunakan 4 byte, dan pada kenyataannya batas tampaknya lebih seperti
2**31
, jadi hanya dengan menggunakan eksponen untuk menghasilkan satu angka besar, batas tersebut tampaknya menghasilkan 2GB. file pyc dari sumber 8 byte. (19**8
Sedikit malu8*2**31
, jadi1<<19**8
memiliki representasi biner tepat di bawah 2GB; perkalian dengan delapan adalah karena kita ingin byte, bukan bit)Namun, tuple juga tidak dapat diubah dan mengalikan tuple juga konstan dilipat, sehingga kita dapat menduplikasi gumpalan 2GB itu sebanyak yang kita inginkan
2**31
, mungkin setidaknya sampai beberapa kali. Untuk4**7
sampai ke 32TB dipilih hanya karena itu adalah eksponen pertama yang saya temukan yang mengalahkan jawaban 16TB sebelumnya.Sayangnya, dengan memori yang saya miliki di komputer saya sendiri, saya bisa menguji ini hanya hingga 2 pengganda, yaitu.
(1<<19**8,)*2
, yang menghasilkan file 8.5GB, yang saya harap menunjukkan bahwa jawabannya realistis (mis. ukuran file tidak terbatas pada 2 ** 32 = 4GB).Juga, saya tidak tahu mengapa ukuran file yang saya dapatkan saat pengujian adalah 8.5GB, bukan 4GB-ish yang saya harapkan, dan file tersebut cukup besar sehingga saya tidak merasa ingin menyentuhnya saat ini.
sumber
(1<<19**8,)*2
? 4GB sudah cukup.1<<18
pada mesin saya (1.5GB) tetapi saya akan mengujinya di linux nanti, di mana saya berharap itu akan bekerja dengan 8GB penuh (tidak akan mencoba versi 32TB!)python -m py_compile asd.py
untuk menghasilkan file .pyc."Templat Haskell" memungkinkan kode Haskell dihasilkan pada waktu kompilasi menggunakan Haskell, dan karenanya merupakan pre-processor yang lengkap.
Inilah upaya saya, yang diparameterisasi oleh ekspresi numerik yang berubah-ubah
FOO
:Keajaiban adalah kode di dalam "sambatan"
$(...)
. Ini akan dieksekusi pada waktu kompilasi, untuk menghasilkan AST Haskell, yang dicangkokkan ke AST program sebagai ganti sambungan.Dalam hal ini, kami membuat AST sederhana yang mewakili literal
0
, kami mereplikasiFOO
kali ini untuk membuat daftar, lalu kami gunakanListE
dariLanguage.Haskell.TH
modul untuk mengubah daftar AST ini menjadi satu AST besar, mewakili literal[0, 0, 0, 0, 0, ...]
.Program yang dihasilkan setara
main = print [0, 0, 0, ...]
denganFOO
pengulangan dari0
.Untuk mengkompilasi ke ELF:
Ini berbobot pada 83 byte (66 untuk kode Haskell dan 17 untuk
-XTemplateHaskell
argumen), ditambah panjangFOO
.Kita dapat menghindari argumen kompiler dan hanya mengompilasinya
ghc
, tetapi kita harus meletakkannya{-# LANGUAGE TemplateHaskell#-}
di awal, yang menabrak kode hingga 97 byte.Berikut adalah beberapa contoh ekspresi untuk
FOO
, dan ukuran biner yang dihasilkan:Saya kehabisan kompilasi dengan RAM
(2^20)
.Kami juga dapat membuat daftar tanpa batas, menggunakan
repeat
bukanreplicate FOO
, tetapi itu mencegah kompiler berhenti;)sumber
[...].replicate (2^10)<$>[|0|])
). Saya tidak berpengalaman dengan Haskell; ada petunjuk tentang cara membuat kompilasi ini?<$>
fungsi ini banyak digunakan di Haskell, tetapi hanya dipindahkan ke "prelude" (sekumpulan fungsi yang tersedia secara default) di GHC 7.10. Untuk versi sebelumnya, Anda harus menambahkanimport Control.Applicative;
setelahimport
pernyataan yang ada. Saya baru saja mencoba dengan GHC 7.8.4 dan berhasil.C ++, 250 + 26 = 276 byte
Ini adalah fungsi Ackermann yang diimplementasikan dalam template. Saya tidak dapat mengkompilasi dengan
h=a<4,2>::n;
mesin kecil (6GB) saya, tetapi saya berhasilh=a<3,14>
untuk file output 26M. Anda dapat menyetel konstanta untuk mencapai batas platform Anda - lihat artikel Wikipedia yang tertaut untuk panduan.Membutuhkan
-g
flag ke GCC (karena itu semua simbol debug yang benar-benar mengkonsumsi ruang apa saja), dan kedalaman templat yang lebih besar dari standar. Baris kompilasi saya berakhir sebagaiInformasi platform
sumber
A+B
di setiap kelas, sekarang saya memikirkannya ...ASM, 61 byte (sumber 29 byte, flag 32 byte), 4.294.975.320 byte dapat dieksekusi
Kompilasi dengan
gcc the_file.s -mcmodel=large -Wl,-fuse-ld=gold
sumber
1<<30
cukup baik untuk C. Karena ini adalah assembler, ukurannya adalah dalam byte.as
berhasil menyerahkanld
, tetapild
gagal dengan ini . Bahkan-mcmodel=medium
sepertinya tidak membantu.gold
:gcc -fuse-ld=gold ...
kompilasi / tautan ... eek! Selesai dalam 1:29 (89 detik) dan ukuran 1.073.748.000 byte.gcc -o g g.s -mcmodel=large -Wl,-fuse-ld=gold
. Penghitungan akhir:,4,294,975,320 bytes
dengan 32 byte tambahan ditambahkan ke panjang program untuk-mcmodel=large -Wl,-fuse-ld=gold
. Perlu dicatat bahwa tajuknya salah; sumbernya adalah 29 byte (tanpa bendera tambahan ditambahkan).1<<33
, saya berakhir dengan8,589,942,616
byte yang dapat dieksekusi.Inilah jawaban C saya dari tahun 2005. Akan menghasilkan biner 16TB jika Anda memiliki RAM 16TB (Anda tidak).
sumber
Preprosesor C biasa: input 214 byte, output 5MB
Terinspirasi oleh preprosesor dunia nyata saya gagal di sini .
Eksperimen menunjukkan bahwa setiap tingkat
#define
kehendak (seperti yang diharapkan) membuat output sekitar sepuluh kali lebih besar. Tetapi karena contoh ini membutuhkan waktu lebih dari satu jam untuk dikompilasi, saya tidak pernah melanjutkan ke "G".sumber
Java, 450 + 22 = 472 sumber byte, ~ file kelas 1GB
B.java (versi golf, peringatan saat kompilasi)
B.java (versi ungolfed)
Kompilasi
Penjelasan
Bom ini menggunakan Prosesor Anotasi. Perlu 2 kompilasi pass. Lulus pertama membangun kelas prosesor
B
. Selama pass kedua prosesor membuat file sumber baruC.java
, dan mengkompilasinya keC.class
dengan ukuran1,073,141,162
byte.Ada beberapa batasan saat mencoba membuat file kelas besar:
error: UTF8 representation for string "iiiiiiiiiiiiiiiiiiii..." is too long for the constant pool
.error: too many constants
.class
file tersebut. Jika saya meningkat16380
menjadi16390
dalam kode di atas compiler tidak pernah kembali..java
file tersebut. Peningkatan16380
ke16400
dalam kode di atas menghasilkan:An exception has occurred in the compiler (1.8.0_66). Please file a bug ...
diikuti oleh ajava.lang.IllegalArgumentException
.sumber
try..finally
(kode pada akhirnya blok diduplikasi untuk kasus normal dan luar biasa) dan blok initializer (kode dari blok initializer ditambahkan ke setiap konstruktor)ä
dengani
dan menyesuaikan angka. Sekarang bom harus membuat kelas 1GB pada sistem apa pun tanpa masalah penyandian. Namun, sekarang membutuhkan lebih banyak memori.C, sumber 26 byte, 2.139.103.367 keluaran, program yang valid
Dikompilasi menggunakan:
gcc cbomb.c -o cbomb
(gcc versi 4.6.3, Ubuntu 12.04, ~ 77 detik)Saya pikir saya akan mencoba melihat seberapa besar saya bisa membuat program yang valid tanpa menggunakan opsi baris perintah apa pun. Saya mendapat ide dari jawaban ini: https://codegolf.stackexchange.com/a/69193/44946 oleh Digital Trauma. Lihat komentar di sana mengapa ini mengkompilasi.
Cara kerjanya:
const
Menghapus bendera tulis dari halaman di segmen, sehingga utama dapat dijalankan. Itu195
adalah kode mesin Intel untuk pengembalian. Dan karena arsitektur Intel adalah little-endian, ini adalah byte pertama. Program akan keluar dengan apa pun kode start up yang dimasukkan ke dalam register eax, kemungkinan 0.Ini hanya sekitar 2 pertunjukan karena linker menggunakan nilai yang ditandatangani 32 bit untuk offset. Ini 8 mc lebih kecil dari 2 manggung karena kompiler / penghubung memerlukan beberapa ruang untuk bekerja dan ini adalah yang terbesar yang bisa saya dapatkan tanpa kesalahan penghubung - ymmv.
sumber
Boo , 71 byte. Waktu kompilasi: 9 menit. Dapat dieksekusi 134.222.236 byte
Menggunakan makro
R
(untuk Ulangi) untuk menyebabkan kompiler mengalikan pernyataan kenaikan beberapa kali secara acak. Tidak diperlukan flag compiler khusus; cukup simpan file sebagaibomb.boo
dan aktifkan kompiler denganbooc bomb.boo
untuk membangunnya.sumber
2**e
-apa ini? Coba9**e
!Kotlin , sumber 90 byte, 177416 byte (173 KB) disusun biner JVM
Secara teknis, Anda bisa membuatnya lebih lama dengan menyarangkan ekspresi lebih jauh. Namun, kompiler macet dengan
StackOverflow
kesalahan jika Anda meningkatkan rekursi.sumber
C ++, 214 byte (tidak diperlukan opsi kompilasi khusus)
Ini adalah rekursi template dua dimensi yang cukup mudah (kedalaman rekursi berjalan sebagai akar kuadrat dari total template yang dipancarkan, sehingga tidak akan melebihi batas platform), dengan sejumlah kecil data statis di masing-masingnya.
File objek yang dihasilkan dengan
g++ 4.9.3 x86_64-pc-cygwin
adalah 2567355421 byte (2.4GiB).Meningkatkan nilai awal di atas 80 akan merusak assembler cygwin gcc (terlalu banyak segmen).
Juga,
99999
dapat diganti dengan9<<19
atau serupa untuk memperbesar ukuran tanpa mengubah kode sumber ... tapi saya tidak berpikir saya perlu menggunakan lebih banyak ruang disk daripada yang sudah saya lakukan;)sumber
-c
flag kompilasi untuk menghentikan linker (2 byte tambahan), dan saya tidak yakin saya dapat menerima output .o (bukan salah satu yang saya daftarkan). Tetap saja, saya menyukainya, jadi +1.Scala - sumber 70 byte, hasil 22980842 byte (setelah tabung)
Ini menghasilkan 9 5 (sekitar 59.000) file kelas khusus, yang dikemas ke dalam toples sekitar 23 MB. Pada prinsipnya Anda dapat terus berjalan jika Anda memiliki sistem file yang dapat menangani banyak file dan cukup memori.
(Jika perintah jar harus dimasukkan, itu 82 byte.)
sumber
error: java.lang.OutOfMemoryError: GC overhead limit exceeded
. Bisakah Anda juga mendokumentasikan perintah yang diperlukan untuk kompilasi?scalac -J-Xmx12G X.scala
Adalah apa yang saya gunakan. Saya tidak menguji berapa yang sebenarnya dibutuhkan.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
Bisakah Anda menentukan versi scala dan java (mungkin platform juga)? Saya menggunakan scalac 2.9.2 dan OpenJDK 1.8.0_66-internal-b17, pada 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 byte + 2 untuk
-c
ingcc bomb.c -o bomb.o -c
; output: 2 147 484 052 bytesumber
Boo, jauh lebih dari yang Anda harapkan dari ini
sumber
Python 3:
Bom tetrasi
sumber