Undefined behavior (UB, nieokreślone zachowanie) to działania w kodzie, których zachowanie standard nie definiuje. W takich przypadkach kompilator może podejmować dowolne decyzje: program może działać różnie na różnych platformach, kompilatorach, a nawet uruchomić wojnę nuklearną (formalnie!). Użycie UB to najniebezpieczniejszy błąd w C++.
Przykłady UB:
int* p = new int[2]; delete[] p; int x = p[1]; // UB: dostęp do pamięci po zwolnieniu
Aby zapobiec UB:
Co się stanie w następującym kodzie?
int a = 42; int b = a++ + ++a;Jaką wartość będzie miał
b?
Odpowiedź:
Dany kod wywołuje UB, ponieważ zmienia i odczytuje zmienną a bez sekwencji punktów sekwencji (sequence points) między operacjami. Standard nie gwarantuje określonego wyniku, a kompilator może uzyskać dowolny wynik lub nawet wygenerować nieoczekiwany kod.
Historia W projekcie systemu magazynowania danych jeden z programistów dopuścił się wyjścia poza granice tablicy w niskopoziomowej funkcji. UB objawiło się tylko na określonych danych użytkownika i prowadziło do zniszczenia struktury pliku i utraty danych klientów.
Historia W projekcie dla mikrokontrolerów pojawiały się konstrukcje z odczytem nie zainicjowanych zmiennych. Testy przechodziły, ale rok po wydaniu urządzenia ujawniono losowe błędy w eksploatacji, spowodowane UB: zmienne czasami zawierały śmieciowe wartości.
Historia W dużym projekcie open-source odkryto deskryptor, który był zwalniany dwa razy z różnych części kodu. To UB początkowo objawiało się niezwykle rzadko, ale w nowych wersjach systemu operacyjnego zaczęło prowadzić do częstych awaryjnych zatrzymań.