programowanieProgramista Embedded C

Jak w C inicjalizowane są zmienne różnych rodzajów przechowywania (automatyczne, statyczne, globalne)? Jak to wpływa na bezpieczeństwo i poprawność działania programu?

Zdaj rozmowy kwalifikacyjne z asystentem AI Hintsage

Odpowiedź

W języku C zmienne inicjalizowane są różnie w zależności od specyfikatora przechowywania:

  • Automatyczne (lokalne) zmienne: mają nieinicjalizowaną (śmieciową) wartość, jeśli nie przypisano im jawnie wartości początkowej. Ich zawartość to pamięć stosu, która była wcześniej używana.
  • Statyczne lokalne i globalne zmienne (static, extern): zawsze są inicjalizowane zerami (dla skalarów — 0, dla wskaźników — NULL) lub podaną wartością na etapie linkowania.

Przykład różnic:

void example() { int a; // automatyczna, nieinicjalizowana static int b; // zainicjalizowana jako 0 printf("a=%d, b=%d ", a, b); } int c; // globalna, zainicjalizowana jako 0

Błędy wynikają z błędnego założenia dotyczącego inicjalizacji. Dla bezpieczeństwa zawsze jawnie inicjalizuj zmienne.

Pytanie przewrotne

Czy automatyczna lokalna zmienna jest inicjalizowana wartością 0, jeśli jest zadeklarowana na poziomie funkcji poza blokiem?

Odpowiedź:

Nie! Nawet jeśli zmienna jest zadeklarowana na początku funkcji, ale bez jawnej inicjalizacji, ma śmieci:

void f() { int x; printf("%d ", x); // UB: x nie zainicjalizowane }

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


Historia

W oprogramowaniu bankowym brak inicjalizacji kolejnego licznika wewnątrz funkcji doprowadził do tego, że czasami był ogromną liczbą ujemną — rezultat: klientowi przypisywano błędne bonusy, błąd wykryto tylko na rzeczywistych danych.


Historia

Multimedialny procesor obrazów na starcie zakładał, że statyczne tablice zawsze są wypełnione zerami. Po przejściu na inny kompilator (z niestandardowym środowiskiem) odkryto segfault — część pamięci nie została fizycznie przydzielona procesowi.


Historia

W bibliotece kryptograficznej programista nie zainicjalizował tymczasowego bufora haseł, sądząc, że bufor z sekcji globalnej jest wypełniony zerami, ale zdarzył się przypadek z pamięcią, gdzie pozostały stare wrażliwe dane. Doprowadziło to do wycieku haseł przy zrzucie.