Errore di battitura di 1 carattere che genera la maggior parte dei messaggi di errore dalla compilazione C ++


51

Sembra che semplici modifiche a un file C ++, in particolare con i modelli, possano generare pagine di errori. Questo concorso è per vedere qual è il più grande "bang of the buck", ovvero l'output dell'errore più dettagliato con la più piccola modifica al codice sorgente (aggiunta di 1 carattere).

Poiché altri linguaggi sono più sani, questo sarà limitato a C ++ e gcc versione 4.x.

Regole

  1. Il file sorgente originale deve essere compilato con gcc 4.9.2 in codice oggetto senza errori.

  2. Un carattere ASCII viene aggiunto al codice sorgente per creare un errore di battitura, aumentando le dimensioni del file di 1 byte.

  3. Il compilatore viene eseguito con le opzioni predefinite. Opzioni necessarie come -ce -std=c++11sono consentite, opzioni come -Wallnon lo sono.

  4. La metrica è

        number of bytes of generated error messages
        -----------------------------------------------------------------------
        (bytes of source code with typo) (length of filename passed to compiler)
    
  5. Le risposte saranno convalidate con http://ideone.com/ C ++ 4.9.2.

Esempio:

Nome file è a.cpp, che è lungo 5 byte.

int foo();

Compilazione di lavoro

 gcc -c a.cpp

Codice sorgente danneggiato:

in t foo();

Compilazione non riuscita

$ gcc -c a.cpp
a.cpp:1:1: error: ‘in’ does not name a type
in t foo();
  ^
$ gcc -c a.cpp |& -c wc
64
$ wc -c a.cpp
12 a.cpp

Punteggio: 64/12/5 = 1.0666

Tentativo migliore: inserire {tra parentesi difoo()

$ gcc -c a.cpp |& wc -c
497

Nuovo punteggio: 497/12/5 = 8.283

In bocca al lupo!

AGGIORNARE

Incoraggio le persone a ignorare l'implementazione ricorsiva. Che tecnicamente vince ma non è nello spirito del concorso.

AGGIORNAMENTO 2

Come molte persone hanno notato, il concorso sarebbe stato probabilmente più interessante se il pre-processore C non fosse stato autorizzato. Quindi vorrei incoraggiare le persone a pubblicare soluzioni che non utilizzano affatto i comandi pre-processore. Ciò non implica alcun uso di alcun file di intestazione, poiché #includenon è consentito!

Per quanto riguarda l'utilizzo di IDEONE per la convalida, è consentito utilizzare l'output IDEONE direttamente (e il nome della sorgente come prog.cpp), oppure è possibile eseguire l'output IDEONE attraverso una ricerca globale e sostituire ( s/prog.cpp/a.cc/ad esempio) e fingere di essere in grado di imposta direttamente il nome del file.

AGGIORNAMENTO 3

Come sottolineato dalla gente, Ideone è un po 'troppo restrittivo e richiede un collegamento non solo la creazione di file oggetto. Poiché questo concorso è puramente all'insegna del divertimento, sii sincero e specifica cosa hai usato per ottenere il tuo punteggio. Usa ideone o usa la build più vaniglia (tutte le impostazioni predefinite) di gcc 4.9.2, come puoi raccogliere. Il concorso ha lo scopo di sensibilizzare l'opinione pubblica sull'importanza dei messaggi di errore C ++.


I commenti non sono per una discussione estesa; questa conversazione è stata spostata in chat . In alternativa, per discussioni su ciò che dovrebbe o non dovrebbe essere considerato un duplicato , si prega di portare la discussione a meta .
Martin Ender,

Tre problemi con l'utilizzo di ideone per la convalida: impone il nome del file sorgente a "prog.cpp", tronca l'output dell'errore del compilatore a 64kB e si collega, aggiungendo ulteriori errori. Quindi non sarà un buon strumento di validazione.
Jason C,

Ho usato GCC 4.9.2 dal repository Ubuntu test-toolchain.
nneonneo,

Quali sono le opzioni predefinite? Per quanto ne so, puoi configurare le opzioni predefinite di gcc al momento della compilazione.
FUZxxl,

2
Riporta ricordi: intorno al 1975 il nostro insegnante di fisica organizzava un concorso annuale "la maggior parte degli errori da 10 (carte a mano) della Fortran" ...
TripeHound,

Risposte:


45

gcc 4.5.2, Punteggio: 8579.15 (o 14367.49 per il nome file "aC", può essere aggiornato in seguito)

File originale, 29 byte, compila pulito (a.cpp):

#if 0
#include"a.cpp"
#endif

File modificato, 30 byte:

#iff 0
#include"a.cpp"
#endif

Errori:

$ gcc -c a.cpp 2>&1 | wc -c
1286873

Punto:

1286873 / (30 * 5) = 8579.15

Testa e coda dell'output dell'errore:

a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:1:2: error: invalid preprocessing directive #iff
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:

... And so on, backing out with second error after max include depth:

a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0,
                 from a.cpp:2:
a.cpp:3:2: error: #endif without #if
In file included from a.cpp:2:0:
a.cpp:3:2: error: #endif without #if
a.cpp:3:2: error: #endif without #if

Nota:
- Se .Csi qualifica come estensione valida, il punteggio è 1.206.869 / (28 * 3) = 14.367,49.
- Se viene aggiunto il secondo #include suggerito da Dennis, il nome del file "a.cpp", il punteggio è 80.797.292.934 / (46 * 5) = 351.292.578,97


2
La domanda dice di aggiungere un personaggio, non di sostituirlo.
Dennis,

3
@Dennis Oh amico. Ho capito. Guarda questa seconda modifica. Il tuo commento è stato una benedizione sotto mentite spoglie.
Jason C,

1
@JasonC Non posso votare abbastanza volte.
Isaacg,

9
Penso che puoi ottenere un punteggio infinito se aggiungi un secondo #include"a.cpp".
Dennis,

3
@Dennis Whoa, bello! Lascerò la risposta così com'è poiché non pensavo di aggiungere un secondo #includeda solo. Per quanto sia infinito ... se è ancora in esecuzione quando mi sveglio domani mattina, è abbastanza infinito per me. Ti terrò aggiornato, ah (anche se al momento sta eseguendo il piping di 5,1 MB / sec wc, quindi se wcsi utilizza un contatore a 32 bit, dai miei calcoli potrebbe accadere qualcosa di strano in circa 13 minuti.)
Jason C

31

CCG 4.9.2, punteggio: 222.898.664 663.393.783

Questo è fortemente basato sulla risposta di @ JasonC , ma ha detto che non voleva prendersi il merito per questo miglioramento.

L'output dell'errore del codice seguente è lungo 126.044.818.789 byte. Il punteggio dovrebbe essere molto più alto in teoria (e tende all'infinito all'aumentare del numero di istruzioni include), ma diminuisce in pratica aggiungendo più istruzioni include.

File originale (37 byte)

/*#
#include"w.cpp"
#include"w.cpp"*/
$ gcc -c w.cpp
$

File modificato (38 byte)

/
*#
#include"w.cpp"
#include"w.cpp"*/
$ gcc -c w.cpp
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0:
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0,
                 from w.cpp:3:
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0,
                 from w.cpp:3,
                 from w.cpp:3:
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
In file included from w.cpp:3:0,
                 from w.cpp:3,
                 from w.cpp:3,
                 from w.cpp:3:
⋮
w.cpp:2:2: error: stray ‘#’ in program
 *#
  ^
w.cpp:3:0: error: #include nested too deeply
 #include"w.cpp"
 ^
w.cpp:4:0: warning: extra tokens at end of #include directive
 #include"w.cpp"*/
 ^
w.cpp:4:0: error: #include nested too deeply
w.cpp:2: confused by earlier errors, bailing out
The bug is not reproducible, so it is likely a hardware or OS problem.

6
Questo non produrrà tecnicamente un output infinito , sebbene, con la tecnologia informatica attuale (o prevedibile), non vivrai abbastanza a lungo da vederlo fermare. Fondamentalmente, GCC ha un #includelimite di nidificazione di 200 livelli, quindi i tuoi ricorsivi #includediventano effettivamente un contatore binario a 200 bit.
Ilmari Karonen,

3
Basta aggiungere più linee di inclusione per ottenere un punteggio infinito. La dimensione dell'output cresce più velocemente del codice.
jimmy23013,

Potrebbe anche essere stato basato su una delle risposte di una domanda precedente .
Peter Taylor,

2
E ha fatto finire questa mattina, con un certo numero enorme che è iniziato con un 8, e ho accidentalmente chiuse la finestra prima di copiare il numero , perché sono impressionanti. Lo sto eseguendo di nuovo.
Jason C,

3
@JasonC Anche io l'ho eseguito e ho ottenuto un output di 77.877.399.160 byte. È molto meno infinito di quanto mi aspettassi, quindi lo eseguirò di nuovo con un nome file più breve.
Dennis,

25

CCG, 4.9.2, Punteggio: 22.2

File originale: 0 byte (a.cpp)

Compila pulito:

$ gcc -c a.cpp |& wc -c
0

File modificato:

(

Errori:

$ gcc -c a.cpp |& wc -c
111

Punto

111/1/5 = 22.2


4
Hai già fatto forza bruta? Voglio dire, è questo il punteggio più alto per un file iniziale di 0 byte?
Thomas Weller,

No, non ho forzato brutalmente questo. Ho appena provato 3 o 4 personaggi diversi. Questa è stata solo una risposta fondamentale per attirare le persone interessate al concorso :)
Mark Lakata,

23

11.126,95 9.105,44 2.359,37 1.645,94 266,88 punti

Più abuso del preprocessore! Questa volta, stiamo facendo piangere la libreria standard.

Senza errori di battitura:

#define typedf
#include<fstream>

Con errore di battitura:

#define typedef
#include<fstream>

Errori:

In file included from /usr/include/c++/4.9/iosfwd:39:0,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/c++/4.9/bits/stringfwd.h:62:33: error: aggregate ‘std::basic_string<char> std::string’ has incomplete type and cannot be defined
   typedef basic_string<char>    string;   
                                 ^
/usr/include/c++/4.9/bits/stringfwd.h:68:33: error: aggregate ‘std::basic_string<wchar_t> std::wstring’ has incomplete type and cannot be defined
   typedef basic_string<wchar_t> wstring;   
                                 ^
/usr/include/c++/4.9/bits/stringfwd.h:78:34: error: aggregate ‘std::basic_string<char16_t> std::u16string’ has incomplete type and cannot be defined
   typedef basic_string<char16_t> u16string; 
                                  ^
/usr/include/c++/4.9/bits/stringfwd.h:81:34: error: aggregate ‘std::basic_string<char32_t> std::u32string’ has incomplete type and cannot be defined
   typedef basic_string<char32_t> u32string; 
                                  ^
In file included from /usr/include/wchar.h:36:0,
                 from /usr/include/c++/4.9/cwchar:44,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/stdio.h:48:25: error: aggregate ‘_IO_FILE FILE’ has incomplete type and cannot be defined
 typedef struct _IO_FILE FILE;
                         ^
/usr/include/stdio.h:64:25: error: aggregate ‘_IO_FILE __FILE’ has incomplete type and cannot be defined
 typedef struct _IO_FILE __FILE;
                         ^
In file included from /usr/include/c++/4.9/cwchar:44:0,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/wchar.h:106:9: error: ‘__mbstate_t’ does not name a type
 typedef __mbstate_t mbstate_t;
         ^
/usr/include/wchar.h:151:38: error: ‘size_t’ is not a type
     const wchar_t *__restrict __src, size_t __n)
                                      ^
/usr/include/wchar.h:159:38: error: ‘size_t’ is not a type
     const wchar_t *__restrict __src, size_t __n)
                                      ^
/usr/include/wchar.h:166:63: error: ‘size_t’ is not a type
 extern int wcsncmp (const wchar_t *__s1, const wchar_t *__s2, size_t __n)
                                                               ^
/usr/include/wchar.h:176:4: error: ‘size_t’ is not a type
    size_t __n) __THROW;
    ^
In file included from /usr/include/wchar.h:180:0,
                 from /usr/include/c++/4.9/cwchar:44,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/xlocale.h:42:9: error: ‘__locale_t’ does not name a type
 typedef __locale_t locale_t;
         ^
In file included from /usr/include/c++/4.9/cwchar:44:0,
                 from /usr/include/c++/4.9/bits/postypes.h:40,
                 from /usr/include/c++/4.9/iosfwd:40,
                 from /usr/include/c++/4.9/ios:38,
                 from /usr/include/c++/4.9/istream:38,
                 from /usr/include/c++/4.9/fstream:38,
                 from a.C:2:
/usr/include/wchar.h:183:5: error: ‘__locale_t’ is not a type
     __locale_t __loc) __THROW;
     ^
/usr/include/wchar.h:186:6: error: ‘size_t’ is not a type
      size_t __n, __locale_t __loc) __THROW;
      ^
/usr/include/wchar.h:186:18: error: ‘__locale_t’ is not a type
      size_t __n, __locale_t __loc) __THROW;
                  ^
/usr/include/wchar.h:196:8: error: ‘size_t’ does not name a type
 extern size_t wcsxfrm (wchar_t *__restrict __s1,
        ^
/usr/include/wchar.h:207:9: error: ‘__locale_t’ is not a type
         __locale_t __loc) __THROW;
         ^
/usr/include/wchar.h:212:8: error: ‘size_t’ does not name a type
 extern size_t wcsxfrm_l (wchar_t *__s1, const wchar_t *__s2,
        ^
/usr/include/wchar.h:252:8: error: ‘size_t’ does not name a type
 extern size_t wcscspn (const wchar_t *__wcs, const wchar_t *__reject)
        ^
/usr/include/wchar.h:256:8: error: ‘size_t’ does not name a type
 extern size_t wcsspn (const wchar_t *__wcs, const wchar_t *__accept)
        ^
/usr/include/wchar.h:287:8: error: ‘size_t’ does not name a type
 extern size_t wcslen (const wchar_t *__s) __THROW __attribute_pure__;
        ^
/usr/include/wchar.h:306:8: error: ‘size_t’ does not name a type
 extern size_t wcsnlen (const wchar_t *__s, size_t __maxlen)
        ^

[Omissis]

/usr/include/c++/4.9/bits/fstream.tcc:934:35: error: ‘cur’ is not a member of ‘std::ios_base’
    __testvalid = this->seekoff(0, ios_base::cur, _M_mode)
                                   ^
/usr/include/c++/4.9/bits/fstream.tcc:934:50: error: ‘_M_mode’ was not declared in this scope
    __testvalid = this->seekoff(0, ios_base::cur, _M_mode)
                                                  ^
/usr/include/c++/4.9/bits/fstream.tcc:941:25: error: ‘_M_state_last’ was not declared in this scope
    + _M_codecvt->length(_M_state_last, _M_ext_buf,
                         ^
/usr/include/c++/4.9/bits/fstream.tcc:944:15: error: ‘streamsize’ does not name a type
         const streamsize __remainder = _M_ext_end - _M_ext_next;
               ^
/usr/include/c++/4.9/bits/fstream.tcc:945:13: error: ‘__remainder’ was not declared in this scope
         if (__remainder)
             ^
/usr/include/c++/4.9/bits/fstream.tcc:949:35: error: ‘__remainder’ was not declared in this scope
         _M_ext_end = _M_ext_buf + __remainder;
                                   ^
/usr/include/c++/4.9/bits/fstream.tcc:951:25: error: ‘_M_state_cur’ was not declared in this scope
         _M_state_last = _M_state_cur = _M_state_beg;
                         ^
/usr/include/c++/4.9/bits/fstream.tcc:951:40: error: ‘_M_state_beg’ was not declared in this scope
         _M_state_last = _M_state_cur = _M_state_beg;
                                        ^
/usr/include/c++/4.9/bits/fstream.tcc:960:2: error: ‘_M_codecvt’ was not declared in this scope
  _M_codecvt = _M_codecvt_tmp;
  ^
/usr/include/c++/4.9/bits/fstream.tcc:960:15: error: ‘_M_codecvt_tmp’ was not declared in this scope
  _M_codecvt = _M_codecvt_tmp;
               ^
/usr/include/c++/4.9/bits/fstream.tcc:962:2: error: ‘_M_codecvt’ was not declared in this scope
  _M_codecvt = 0;
  ^

Sulla mia macchina Ubuntu, g++-4.9 -std=c++11 -c a.Cgenera 1.101.568 gloriosi byte di errori, per un punteggio di 1101568/33/3 = 11.126,95.


7
Dovresti scrivere un programma per analizzare tutte le intestazioni standard e determinare quale #defineti dà più punti.
Jason C,

1
Puoi peggiorarlo ulteriormente sostituendolo typedefcon t;. Ora non solo interrompi ogni uso typedefma ricevi anche una tonnellata di errori "t non nomina un tipo". O %;per produrre "ID non qualificato previsto prima del token%".
Saluti

1
#define typename *e #define int class stdsembrava generare molti più errori.
jimmy23013,

11

62.93 punti

Solo un po 'di magia nera meta C ++, compilata con g++-4.8 -c -std=c++11 a.cc:

#include<memory>
template<int n>class B:std::unique_ptr<B<n-1>>{};template<>class B<0>{};B<-1>x;

Ungolfed:

#include <memory>

template<int n>
class B: std::unique_ptr<B<n-1>> {};

template<>
class B<0> {};

B<-1>x;

G ++ ha un limite di ricorsione di 900, quindi passare B<1>a B<-1>un intervallo di 31 bit ha un effetto ... interessante.

  • 96 byte di codice (senza contare il finale che \nalcuni editor di testo aggiungono automaticamente, vimno).
  • Nome file di 4 lettere, a.cc
  • 24165 byte di messaggio di errore ed è troncato. Il messaggio di errore completo ha un enorme 1235889 byte di contenuto. Richiederebbe l' -ftemplate-backtrace-limit=0interruttore. Significherebbe anche 3185 punti per me!

std::unique_ptr è solo la classe di template che riesce a emettere il messaggio di errore più lungo, trovato per tentativi ed errori e conoscenza dell'STL e dei gatti e cose del genere.


2
Ma ... come posso eliminare 6 spazi bianchi quando ne ho solo 3 nel codice, @JasonC!
Stefano Sanfilippo,

7

Punteggio 7,865

A rigor di termini, la risposta a 0 byte NON è corretta, poiché ideone.com rifiuterà di compilare il file senza errori. Lo stesso vale con l'esempio int foo();: non verrà compilato su ideone.com (non riesco a commentare a causa della reputazione mancante ...)

Quindi il programma più piccolo possibile da compilare senza nessuno #includesè questo:

int main(){}

Se lo cambi al seguente codice, fallirà con 409 byte di codice di errore (dopo aver rinominato prog.cpp in a.cc dall'output di ideone.com):

int main(){[}

409 / (13 * 4) = 7.865

Aggiorna la domanda di conseguenza, poiché gli esempi forniti non rispettano le regole indicate ...


1
L'intera cosa dell'ideone è una specie di sciocco.
Jason C,

Sono d'accordo, ho aderito alla regola dell'ideone dopo che la domanda è stata pubblicata e le prime risposte fornite. Il gatto è un po 'fuori dalla borsa ora.
Mark Lakata,

1

C, chiamato come .cc

main(){constexprs a(){*(int*)0=f;}a(0)}

Codice di errore:

.code.tio.cpp: In function ‘int main()’:
.code.tio.cpp:1:8: error: ‘constexprs’ was not declared in this scope
 main(){constexprs int a(f){*(int*)0=f;}a(0);}
        ^~~~~~~~~~
.code.tio.cpp:1:8: note: suggested alternative: ‘__cpp_constexpr’
 main(){constexprs int a(f){*(int*)0=f;}a(0);}
        ^~~~~~~~~~
        __cpp_constexpr
.code.tio.cpp:1:40: error: ‘a’ was not declared in this scope
 main(){constexprs int a(f){*(int*)0=f;}a(0);}

Ciao di nuovo! Qual è il programma originale che non presenta errori? (Suppongo che lo sia main(){}, ma non ne sono sicuro) Inoltre, non è solo un miglioramento della risposta sopra? Sebbene tu possa certamente mantenere questa risposta, se è stata ispirata dalla risposta di @ StefanM, dovresti menzionarlo. Finalmente, ora che hai 50 rappresentanti, puoi commentare ovunque.
NoOneIsHere

Penso che questo sia troppo vicino alla risposta di Stefan M.; Vorrei pubblicare questo come un miglioramento raccomandato per quella soluzione. Detto questo, sono consentite risposte duplicate. Per favore, metti qui l'originale e menziona eventuali ispirazioni (anche se è possibile che tu l'abbia
inventato

1

Punteggio 12.xx (errore ELIMINANDO un carattere)

Per favore, perdona la violazione della Regola 2 (l'aggiunta di IMHO o la cancellazione di un personaggio sarebbe nello spirito della regola), ma questo mi è successo accidentalmente (quindi non usa trucchi "intenzionali") durante la scrittura di Real Code (TM) - sia il codice funzionante che quello che causa l'errore sono (o sembrano) semplici e diretti, quindi ho pensato che fosse abbastanza pulito da includere qui. Codice originale

#include <iostream>
using namespace std;
int main ()
{
cout<<"test"<<endl;
}

Codice che genera l'errore (l'ultimo '<' è stato eliminato in modo che appaia meno di un confronto, ma noooooooooooo ...)

#include <iostream>
using namespace std;
int main ()
{
cout<<"test"<endl;
}

Sono "solo" 8241 byte di messaggi di errore del compilatore in ideone.com g ++ 4.3.2.


1
Anche se sembra essere nello spirito della sfida (dal momento che il titolo dice "un errore di battitura"), questo non segue la regola 2 che dice che puoi solo aggiungere un personaggio, non cancellare o cambiare.
Jo King,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.