programowanieProgramista systemowy, Programista Backend

Co to jest undefined behavior (nieokreślone zachowanie) w C++ i dlaczego jest to niebezpieczne? Podaj przykłady i wyjaśnij, jak go unikać.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

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:

  • Dostęp poza granice tablicy
  • Używanie nie zainicjowanych zmiennych
  • Zwolnienie jednej sekcji pamięci dwa razy
  • Używanie dangling pointers (wiszące wskaźniki)
int* p = new int[2]; delete[] p; int x = p[1]; // UB: dostęp do pamięci po zwolnieniu

Aby zapobiec UB:

  • Zawsze inicjuj zmienne;
  • Sprawdzaj granice tablic/kontenerów;
  • Unikaj ręcznego zarządzania pamięcią, używaj smart pointers.

Pytanie z podstępem.

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.

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


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