Niezdefiniowane zachowanie (Undefined Behavior, UB) — to sytuacja, w której standard języka nie określa zachowania programu. Kompilator może zrobić z programem cokolwiek: program może się zawiesić, dać błędny wynik lub nawet 'działać'. UB występuje z powodu błędów, takich jak wyjście poza tablicę, dereferencja wskaźnika null itp.
int arr[5]; arr[10] = 42; // UB: wyjście poza granice tablicy int* p = nullptr; *p = 1; // UB: dereferencja 0
Unikaj UB poprzez przestrzeganie standardów, użycie nowoczesnych narzędzi (ASan, UBSan, valgrind), staraj się nie używać surowych wskaźników i pisać bezpieczny kod.
Jeśli UB wystąpił w jednej części programu, czy może to wpłynąć na zupełnie inną, 'niezależną' część kodu?
Tak! Kompilator podczas optymalizacji może wprowadzić nieoczekiwane przekształcenia, gdy odkryje, że wystąpiło UB.
void foo(int* p) { if (p == nullptr) return; *p = 5; // A jeśli p nie był nullptr, to UB! Ale kompilator może usunąć sprawdzenia, zakładając, że p jest zawsze poprawny. }
Historia
Na serwerze dużej firmy z powodu dereferencji wskaźnika null od czasu do czasu zdarzały się losowe awarie procesu, które trudno było odtworzyć: w debug wszystko działało, a w wersji release — nie.
Historia
Podczas portowania kodu z 32-bitowego na 64-bitowy pomylono typy danych, używając rzutowania między int a wskaźnikiem. Na niektórych maszynach działało, na innych występowały awarie i dziwne artefakty.
Historia
W internecie znany jest przypadek, gdy niegroźne UB (wyjście poza granice tablicy) psuło działanie całego programu: kompilator usunął nie tylko operacje na tablicy, ale i 'zaoptymalizował' część kodu, która nie była w żaden sposób związana z błędem.