programowanieProgramista systemowy C++

Co to jest niezdefiniowane zachowanie (undefined behavior) w C++? Podaj przykłady i opowiedz, jak go unikać.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

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.

Przykład eksplicytnego UB:

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.

Pytanie podchwytliwe.

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.

Przykład:

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. }

Przykłady rzeczywistych błędów z powodu nieznajomości niuansów tematu.


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.