Il comportamento indefinito (UB, undefined behavior) è un'azione nel codice il cui comportamento non è definito dallo standard. In questi casi, il compilatore è libero di prendere qualsiasi decisione: il programma potrebbe comportarsi in modo diverso su diverse piattaforme, compilatori o addirittura innescare una guerra nucleare (formalmente!). L'uso di UB è l'errore più pericoloso in C++.
Esempi di UB:
int* p = new int[2]; delete[] p; int x = p[1]; // UB: accesso alla memoria dopo la deallocazione
Per prevenire l'UB:
Cosa succede con il seguente codice?
int a = 42; int b = a++ + ++a;Qual è il valore di
b?
Risposta:
Questo codice provoca UB, poiché modifica e legge la variabile a senza una sequenza di punti di sequenza (sequence points) tra le operazioni. Lo standard non garantisce un risultato definito, e il compilatore può ottenere qualsiasi risultato o addirittura generare codice inaspettato.
Storia In un progetto di sistema di archiviazione dati, uno degli sviluppatori ha causato un'uscita oltre i limiti dell'array in una funzione a basso livello. L'UB si manifestava solo con specifici dati degli utenti e portava alla corruzione della struttura del file e alla perdita di dati dei clienti.
Storia In un progetto per microcontrollori si sono incontrate strutture con lettura di variabili non inizializzate. I test hanno passato, ma un anno dopo l'uscita del dispositivo si sono verificate falsi errori in esercizio, causati dall'UB: le variabili a volte contenevano valori spazzatura.
Storia In un grande progetto open-source è stato trovato un descrittore deallocato due volte in parti diverse del codice. Questo UB inizialmente si manifestava molto raramente, ma nelle nuove versioni del sistema operativo ha cominciato a causare arresti anomali frequenti.