Menulis sebuah program pendek, yang akan menghasilkan pesan kesalahan selama mungkin, dalam standar C ++ compiler ( gcc
, cl.exe
, icc
, atau clang
).
Skor setiap entri adalah jumlah karakter dalam pesan kesalahan terpanjang yang dikompilasi oleh kompiler. Jenis yang termasuk dalam kode sumber Anda dan dikutip oleh kompiler dihitung sebagai satu karakter.
Selingkuh
Anda selalu dapat mendefinisikan ulang templat di templat di templat dengan nama yang panjang, tapi saya mengharapkan sesuatu yang kreatif. Saya mencoba untuk mencegah beberapa dari itu dengan aturan terakhir, tetapi tentu saja aturannya bisa lebih baik, dan saya akan senang untuk perbaikan.
code-challenge
c++
error-message
Elazar Leibovich
sumber
sumber
Error.message.length / code.length
.Jawaban:
Pesan kesalahan template menyenangkan untuk diuraikan. Pertimbangkan ini:
Kompilasi dengan
gcc -c error.cpp
(4.6.3) akan menghasilkan 15786 byte output, dengan garis terpanjang 330 karakter.Sunting 2016-04-29: gcc 5.3.0 membuatnya sedikit lebih baik: hanya 9300 byte, baris terpanjang 361 karakter ...
Edit 2019-04-04: gcc 6.5.0: 11237 byte, tetapi memberikan beberapa petunjuk tentang kesalahan, seperti pada baris tesis:
sumber
19 karakter
Buat file
a.cpp
dengan konten ini:Kompilasi sebagai:
dan dapatkan pesan kesalahan 21300 baris yang luar biasa :
...
... 21280 garis kesalahan ...
...
sumber
#include __FILE__
dan nama file yang sangat panjang ..?clang++ -ferrorlimit=1000 a.cpp
. Baris terpanjang adalah 466 karakter.98 karakter (diperlukan):
Menghasilkan output kesalahan berikut dalam GCC (4.4.5):
Statistik:
Tidak dikumpulkan (menghasilkan output yang lebih lama):
Saya menemukan ini ketika saya ingin melihat apakah C ++ mendukung rekursi polimorfik (dan, seperti yang Anda lihat dengan jelas, tidak). Berikut adalah contoh sepele rekursi polimorfik di Haskell:
Di sini, ini membutuhkan Haskell untuk bertindak seperti itu instantiates
Show x
,Show [x]
,Show [[x]]
,Show [[[x]]]
, tak terhingga. Haskell melakukannya dengan mengubah(Show x) =>
menjadi parameter implisit ke fungsi yangf
ditambahkan oleh kompiler, sesuatu seperti ini:C ++ melakukannya dengan benar-benar mencoba untuk membangun contoh tersebut sampai kedalaman instantiation template terlampaui.
sumber
cl
tidak suka implisitint
dalam mode C ++) itu menghasilkan 14.380.923 byte output kesalahan setelah 4½ menit waktu CPU dan puncak sekitar 100 MiB penggunaan memori.Berdasarkan rasio panjang pesan / panjang kode, ini mungkin solusi terbaik:
Pesan (81):
81/0 = Inf
sumber
279 karakter
Dengan gcc 4.2.1, menghasilkan kesalahan
error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘foofoo....foofoo’
dengan 2 ^ 21 salinanfoo
. Semuanya 6.291.558 byte. Ini tentang pengidentifikasi sebesar yang saya dapat, menggantikanfoo
denganfood
menghasilkan ICE.sumber
#define A(s) s##s##s##s #define B(s) A(s) #define C(s) B(B(B(s))) #define D(s) C(C(C(s))) D(foo)
. Ini memberi saya pesan kesalahan tentang selama dengan kode jauh lebih sedikit, dan tumbuh lebih cepat dengan meningkatkan pola di dimensi apa pun, karena kami pada dasarnya menerapkan fungsi Ackermann.Mirip dengan VJo:
a.cpp:
g ++ a.cpp
menghasilkan banyak output (setidaknya 2 gigabyte sebelum saya membunuhnya)
sumber
Kode berikut didasarkan pada kesalahan aktual yang pernah saya temui.
(menggunakan gcc)
Rekursi templat yang cukup jelas, tetapi karena saya gunakan
ftemplate-depth=100000
untuk menjalankan ini tidak menghasilkan kesalahan. Sumber sebenarnya dari pesan kesalahan berasalchar baz[i];
, yang menghasilkan kesalahan saati
turun ke -1.Setelah sekitar setengah jam, saya duduk di 21.000 kesalahan kompiler , 300.000 baris pesan kesalahan , dan 280 megabita RAM yang digunakan oleh kompiler. Dan itu tidak menunjukkan tanda-tanda berhenti.
SUNTING:
Satu jam kemudian, sekarang ada 36.000 kesalahan kompiler , 504.000 baris pesan kesalahan , dan 480 megabita RAM ... dan masih berjalan.
EDIT # 2:
Sekitar setengah jam kemudian:
Statistik akhir: 38.876 kesalahan kompiler , 544.624 baris pesan kesalahan, total data 48,8 megabita , dan 518,9 megabita RAM yang digunakan oleh kompiler sebelum terhenti .
sumber
28 byte
Menyabotase perpustakaan standar:
Menggunakan dentang pada OS X 10.9:
456 baris kesalahan, 50 kesalahan, dan segfault kompiler !
Versi dentang:
sumber
Saya sengaja menemukan ini:
Pada c ++ x11 itu menghasilkan 44kb pesan kesalahan, di mana kompiler mencoba mengatakan: Silakan tentukan placeholder untuk argumen pertama jika Anda mendefinisikannya untuk yang kedua.
Lihat di ideone .
sumber
C ++
Berdasarkan solusi BЈовић:
File: golf.cpp:
Menjalankan ini di bawah G ++ tidak akan selesai, namun, saya telah menghitung panjang kesalahan yang pada akhirnya akan memancarkan sekitar 85 * 2 ^ 140 terabyte.
sumber
C ++ 11 templat variadik (69 karakter)
Mengkonfigurasi kedalaman instan templat maksimum, Anda dapat mengatur panjang kesalahan. Berikut adalah contoh menggunakan GCC 4.8.1 dengan kedalaman templat default (900):
Anda juga dapat menambahkan sepuluh karakter lagi dan menggunakan underflow integer yang tidak ditandatangani untuk menambah panjang kesalahan:
Berikut ini contoh menjalankan ideone.
sumber
82 byte: Yang ini bekerja mirip dengan pendekatan Joey Adams , tetapi pesan kesalahan akan tumbuh secara eksponensial sehubungan dengan
-ftemplate-depth
(karenastd::set<T>
sebenarnyastd::set<T, std::less<T>, std::allocator<T>>
).Sebab
(x = -ftemplate-depth) >= 28
, akan ada 1460 × 3 x-27 + 269x - 5381 byte pesan kesalahan (dikompilasi oleh gcc 7.2.0). Artinya, dalam pengaturan default (x = 900), itu akan menampilkan sekitar 4,9 × 10 419 byte pesan kesalahan secara teoritis.Perhatikan bahwa tanpa
return
pernyataan, pesan kesalahan hanya akan dihasilkan pada akhir kompilasi. (jadi dalam pengaturan default Anda tidak akan mendapatkan pesan - Anda akan kehabisan memori lebih dulu.)Peringatan: Mengkompilasi program ini akan menghabiskan banyak memori.
Cobalah online!
sumber
map
tampaknya ketat lebih jahat, karenastd::map<T,T>
inistd::map<T,T,std::less<T>,std::allocator<std::pair<T,T>>>
sehingga Anda mendapatkan rekursi 5 arah bukan 3, karena hanya 2 byte.-ftemplate-depth=13
, 423.572 byte pada-ftemplate-depth=14
, dan 1.247.322 byte pada-ftemplate-depth=15
.map
varian menghasilkan 13.373.990 byte pada kedalaman 14 dan 66.759.871 byte pada kedalaman 15.-ftemplate-depth=1024
, yang berarti suatu tempat di utara 10 ^ 713 byte denganmap
varian. Saya percaya ini berarti Anda menang ...Ini menghasilkan keluaran tanpa batas pada GCC 5.2 dan Dentang 3.6 (pada Dentang membutuhkan
-ferror-limit=0
, pada GCC berfungsi dengan pengaturan default):sumber
File bernama
a.cpp
. Kode:Ini adalah bom fork dengan n = 40.
sumber
=>
=>
kompilasi dengan
index_afterence tampaknya mem-bypass masalah batas kedalaman instantiation template
kesalahan terlihat seperti ini: seluruh 0 ... C-1 urutan angka sepertinya dicetak 4 * C kali
dan urutan angka dapat melewati batas kedalaman instantiasi template default, tentu saja karena itu adalah builtin:
sumber