Podsumowanie :
Czy funkcja w C zawsze powinna sprawdzać, aby upewnić się, że nie usuwa dereferencji ze NULL
wskaźnika? Jeśli nie, kiedy należy pominąć te kontrole?
Szczegóły :
Czytałem kilka książek o programowaniu wywiadów i zastanawiam się, jaki jest odpowiedni stopień sprawdzania poprawności danych wejściowych dla argumentów funkcji w C? Oczywiście każda funkcja, która pobiera dane wejściowe od użytkownika, musi przeprowadzić walidację, w tym sprawdzić NULL
wskaźnik przed usunięciem go z listy. Ale co w przypadku funkcji w tym samym pliku, której nie spodziewasz się ujawnić za pośrednictwem interfejsu API?
Na przykład następujący pojawia się w kodzie źródłowym git:
static unsigned short graph_get_current_column_color(const struct git_graph *graph)
{
if (!want_color(graph->revs->diffopt.use_color))
return column_colors_max;
return graph->default_column_color;
}
Jeśli *graph
jest, NULL
wówczas zerowy wskaźnik zostanie usunięty z dereferencji, prawdopodobnie zawieszając program, ale prawdopodobnie powodując inne nieprzewidziane zachowanie. Z drugiej strony funkcja jest, static
więc może programista już zatwierdził dane wejściowe. Nie wiem, wybrałem go losowo, ponieważ był to krótki przykład w aplikacji napisanej w C. Widziałem wiele innych miejsc, w których używane są wskaźniki bez sprawdzania wartości NULL. Moje pytanie nie jest ogólne dla tego segmentu kodu.
Widziałem podobne pytanie zadawane w kontekście przekazywania wyjątków . Jednak w przypadku niebezpiecznego języka, takiego jak C lub C ++, nie występuje automatyczne propagowanie błędów nieobsługiwanych wyjątków.
Z drugiej strony widziałem dużo kodu w projektach typu open source (takich jak powyższy przykład), które nie sprawdzają wskaźników przed ich użyciem. Zastanawiam się, czy ktoś ma przemyślenia na temat tego, kiedy należy sprawdzać funkcję, czy zakładać, że funkcja została wywołana z poprawnymi argumentami.
Ogólnie interesuje mnie to pytanie dotyczące pisania kodu produkcyjnego. Ale interesuję się również w kontekście wywiadów programistycznych. Na przykład wiele podręczników algorytmów (takich jak CLR) ma tendencję do przedstawiania algorytmów w pseudokodzie bez sprawdzania błędów. Jednak chociaż jest to dobre dla zrozumienia rdzenia algorytmu, to oczywiście nie jest dobrą praktyką programowania. Nie chciałbym więc mówić ankieterowi, że pomijam sprawdzanie błędów, aby uprościć przykłady kodu (tak jak w podręczniku). Ale nie chciałbym też wydawać się, że produkuje nieefektywny kod z nadmierną kontrolą błędów. Na przykład graph_get_current_column_color
można go zmodyfikować, aby sprawdzał, czy ma *graph
wartość NULL, ale nie jest jasne, co by zrobił, gdyby *graph
miał wartość NULL, inaczej niż nie powinien go wyłapywać.