programowanieProgramista C

Co to jest 'undefined behavior' w języku C? Podaj przykłady jego występowania i sposoby minimalizacji takich problemów.

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź.

Undefined Behavior (UB) — to zachowanie programu, którego wynik nie jest określony przez standard języka C. Kompilator lub system mogą wprowadzać dowolne działania — od subtelnej pomyłki po całkowite awarie lub uszkodzenie danych.

Typowe przyczyny UB:

  • Dostęp poza granice tablicy
  • Dereferencja nieinicjalizowanego/nieważnego wskaźnika
  • Dzielenie przez 0
  • Modyfikacja stałych

Jak minimalizować UB:

  • Zawsze inicjalizuj zmienne
  • Sprawdzaj indeksy tablic
  • Używaj statycznych i dynamicznych analizatorów kodu (np. valgrind, AddressSanitizer)

Przykład kodu:

int arr[5]; arr[10] = 0; // UB — wyjście poza granice tablicy int* p = NULL; *p = 42; // UB — dereferencja wskaźnika NULL

Pytanie z pułapką.

Pytanie: Jak zachowa się program, gdy wykonasz dzielenie liczby całkowitej przez zero?

Odpowiedź: Zgodnie ze standardem C (ISO C99 6.5.5), dzielenie przez 0 to undefined behavior. Może wystąpić awaria, pojawienie się śmieci lub nawet „logicznie poprawny” wynik, ale standard nie gwarantuje żadnego rezultatu.

Przykład kodu:

int a = 10, b = 0; printf("%d", a / b); // Undefined behavior

Historia

W jednym z projektów na systemach wbudowanych programista napisał pętlę po tablicy, przypadkowo przekraczając jej granice o jeden element. Aplikacja działała normalnie, ale po miesiącu zaczęły występować uszkodzenia innych danych w pamięci (krótkotrwałe błędy, trudne do odtworzenia). Problem wykryto dopiero po dokładnym przeglądzie i kontroli za pomocą analizatora statycznego.


Historia

Programista polegał na tym, że dereferencja wskaźnika NULL zawsze powoduje awarię, dlatego nie dodawał sprawdzeń na NULL. Jednak na rzadkiej platformie prowadziło to do niepoprawnej (ale nie fatalnej) modyfikacji pamięci, co łamało inne struktury i prowadziło do trudnych do uchwycenia błędów.


Historia

Podczas generowania liczb pseudolosowych stosowano dzielenie, i dla niektórych wartości argumentów wejściowych występowało dzielenie przez 0. Na większości platform program zwykle „przypadł”, ale na jednej z nich wynik był niepoprawną liczbą, co prowadziło do niemożności odtworzenia błędów między różnymi środowiskami.