Napisać krótki program, który generuje najdłuższy komunikat o błędzie, w standardowej C ++ ( gcc
, cl.exe
, icc
, lub clang
).
Wynik każdego wpisu to liczba znaków w najdłuższym komunikacie o błędzie emitowanym przez kompilator. Typy zawarte w kodzie źródłowym i cytowane przez kompilator są liczone jako pojedynczy znak.
Oszukiwanie
Zawsze możesz przedefiniować szablon w szablonie w szablonie o długich nazwach, ale oczekuję czegoś kreatywnego. Starałem się temu zapobiec przez ostatnią zasadę, ale oczywiście reguły mogą być lepsze i będę zadowolony z ulepszeń.
code-challenge
c++
error-message
Elazar Leibovich
źródło
źródło
Error.message.length / code.length
.Odpowiedzi:
Komunikaty o błędach szablonu są łatwe do rozszyfrowania. Rozważ to:
Kompilacja z
gcc -c error.cpp
(4.6.3) da 15786 bajtów danych wyjściowych, z najdłuższą linią 330 znaków.Edytuj 2016-04-29: gcc 5.3.0 ma to trochę lepiej: tylko 9300 bajtów, najdłuższa linia ma 361 znaków ...
Edytuj 2019-04-04: gcc 6.5.0: 11237 bajtów, ale daje kilka wskazówek na temat błędu, jak w tych wierszach:
źródło
19 znaków
Utwórz plik
a.cpp
o tej treści:Kompiluj jako:
i otrzymuj niesamowite komunikaty o błędach 21300 linii :
...
... 21280 linii błędów ...
...
źródło
#include __FILE__
z bardzo długą nazwą pliku ...?clang++ -ferrorlimit=1000 a.cpp
. Najdłuższa linia ma 466 znaków.98 (niezbędnych) znaków:
Powoduje wygenerowanie następującego błędu w GCC (4.4.5):
Statystyka:
Niegolfowany (daje dłuższą produkcję):
Odkryłem to, gdy chciałem sprawdzić, czy C ++ obsługuje rekurencję polimorficzną (i, jak widać, nie działa). Oto trywialny przykład polimorficznej rekurencji w Haskell:
Tutaj, to wymaga Haskell zachowywać się jak to wystąpienie
Show x
,Show [x]
,Show [[x]]
,Show [[[x]]]
, ad infinitum. Haskell robi to, zamieniając się(Show x) =>
w parametr niejawny dla funkcjif
dodanej przez kompilator, mniej więcej tak:C ++ robi to, dosłownie próbując skonstruować takie instancje, dopóki nie zostanie przekroczona głębokość tworzenia szablonu.
źródło
cl
nie lubi tego domyślnieint
w trybie C ++) generuje 14.380.923 bajtów wyjścia błędu po 4½ minutach czasu procesora i szczytowym zużyciu pamięci około 100 MiB.W oparciu o stosunek długości wiadomości do długości kodu może to być najlepsze rozwiązanie:
Wiadomość (81):
81/0 = Inf
źródło
279 znaków
W gcc 4.2.1 generuje błąd
error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘foofoo....foofoo’
z 2 ^ 21 kopiamifoo
. Łącznie 6 291 558 bajtów. Jest to tak duży identyfikator, jak tylko mogę, zastąpieniefoo
gofood
generuje ICE.źródło
#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)
. Daje mi to komunikat o błędzie o tak długim czasie i znacznie mniejszym kodzie, i rośnie znacznie szybciej wraz ze zwiększaniem wzorca w dowolnym wymiarze, ponieważ zasadniczo implementujemy funkcję Ackermann.Podobne do VJo:
a.cpp:
g ++ a.cpp
produkuje dużo danych wyjściowych (przynajmniej 2 gigabajty, zanim je zabiłem)
źródło
Poniższy kod opiera się na rzeczywistym błędzie, który napotkałem kiedyś.
(używając gcc)
Dość oczywista rekurencja szablonu, ale ponieważ użyłem
ftemplate-depth=100000
tego uruchomienia, nie powoduje to błędu. Rzeczywiste źródło komunikatów o błędach pochodzichar baz[i];
, co powoduje błąd, gdyi
spada do -1.Po około pół godzinie siedzę przy 21 000 błędów kompilatora , 300 000 linii komunikatów o błędach i 280 megabajtów pamięci RAM używanych przez kompilator. I nie wykazuje żadnych oznak zatrzymania się.
EDYTOWAĆ:
Godzinę później, teraz przy 36 000 błędów kompilatora , 504 000 linii komunikatów o błędach i 480 megabajtów pamięci RAM ... i nadal działa.
EDYCJA 2:
Około pół godziny później:
Ostateczne statystyki: 38 876 błędów kompilatora , 544,624 wierszy komunikatów o błędach, w sumie 48,8 megabajtów danych oraz 518,9 megabajtów pamięci RAM używanych przez kompilator przed jego awarią .
źródło
28 bajtów
Sabotowanie standardowej biblioteki:
Używanie clang w OS X 10.9:
456 linii błędów, 50 błędów i segfault kompilatora !
Wersja Clang:
źródło
Natknąłem się na to przez przypadek:
Na c ++ x11 generuje 44kb komunikatów o błędach, w których kompilator próbuje powiedzieć: Proszę zdefiniować symbol zastępczy dla pierwszego argumentu, jeśli zostanie zdefiniowany dla drugiego.
Zobacz na ideone .
źródło
C ++
W oparciu o rozwiązanie BЈовић:
Plik: golf.cpp:
Uruchomienie tego w G ++ nie zakończy się, jednak obliczyłem długość błędu, który ostatecznie wyemituje, jako około 85 * 2 ^ 140 terabajtów.
źródło
Wariantowe szablony C ++ 11 (69 znaków)
Konfigurując maksymalną głębokość tworzenia szablonu, możesz ustawić długość błędu. Oto przykład z użyciem GCC 4.8.1 z domyślną głębokością szablonu (900):
Możesz także dodać kolejne dziesięć znaków i użyć niedopełnienia liczby całkowitej bez znaku, aby zwiększyć długość błędu:
Oto przykład działający w ideone.
źródło
82 bajty: Ten działa podobnie do podejścia Joeya Adamsa , ale komunikat o błędzie wzrośnie wykładniczo w stosunku do
-ftemplate-depth
(bostd::set<T>
tak naprawdę jeststd::set<T, std::less<T>, std::allocator<T>>
).W przypadku
(x = -ftemplate-depth) >= 28
, nie będzie 1460 x 3 x-27 + 269x - 5381 bajtów komunikatów (opracowane przez gcc 7.2.0). Oznacza to, że w ustawieniach domyślnych (x = 900) wyśle teoretycznie około 4,9 × 10 419 bajtów komunikatu o błędzie .Zauważ, że bez
return
instrukcji komunikaty o błędach pojawią się dopiero na końcu kompilacji. (więc w ustawieniach domyślnych nie otrzymasz wiadomości - najpierw zabraknie ci pamięci).Ostrzeżenie: Kompilowanie tego programu zużywa dużo pamięci.
Wypróbuj online!
źródło
map
wydaje się zdecydowanie bardziej złe, ponieważstd::map<T,T>
jeststd::map<T,T,std::less<T>,std::allocator<std::pair<T,T>>>
tak, że dostajesz rekurencję w 5 kierunkach zamiast 3, za tylko 2 kolejne bajty.-ftemplate-depth=13
, 423 572 bajtów przy-ftemplate-depth=14
i 1 247 322 bajtów przy-ftemplate-depth=15
.map
wariant generuje 13 373 990 bajtów na głębokości 14 i 66 759 871 bajtów na głębokości 15.-ftemplate-depth=1024
, co oznacza gdzieś na północ od 10 ^ 713 bajtów zmap
wariantem. Wierzę, że to oznacza, że wygrywasz ...Daje to nieskończoną moc wyjściową w GCC 5.2 i Clang 3.6 (w Clang wymaga
-ferror-limit=0
, w GCC działa z ustawieniami domyślnymi):źródło
Plik o nazwie
a.cpp
. Kod:To bomba rozwidlona, gdzie n = 40.
źródło
=>
=>
Połącz z
wydaje się, że indeks_sekwencja omija problem z limitem głębokości tworzenia szablonów
błędy wyglądają tak: cała sekwencja liczb 0 ... C-1 wygląda na wydrukowaną 4 * C razy
a sekwencje numerów mogą przekroczyć domyślny limit głębokości tworzenia szablonów, na pewno dlatego, że jest to wbudowane:
źródło