Riepilogo :
Una funzione in C dovrebbe sempre verificare per assicurarsi che non stia dereferenziando un NULL
puntatore? In caso contrario, quando è opportuno saltare questi controlli?
Dettagli :
Ho letto alcuni libri sulle interviste di programmazione e mi chiedo quale sia il grado appropriato di convalida dell'input per gli argomenti delle funzioni in C? Ovviamente qualsiasi funzione che accetta input da un utente deve eseguire la validazione, incluso il controllo di un NULL
puntatore prima di dereferenziarlo. Ma per quanto riguarda una funzione all'interno dello stesso file che non ti aspetti di esporre attraverso la tua API?
Ad esempio, nel codice sorgente di git appare quanto segue :
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;
}
Se *graph
è NULL
quindi un puntatore nullo verrà dereferenziato, probabilmente arrestando in modo anomalo il programma, ma probabilmente comportando qualche altro comportamento imprevedibile. D'altra parte la funzione è static
e quindi forse il programmatore ha già convalidato l'ingresso. Non lo so, l'ho selezionato a caso perché era un breve esempio in un programma applicativo scritto in C. Ho visto molti altri posti in cui i puntatori vengono utilizzati senza controllare NULL. La mia domanda non è generalmente specifica per questo segmento di codice.
Ho visto una domanda simile posta nel contesto della gestione delle eccezioni . Tuttavia, per un linguaggio non sicuro come C o C ++ non esiste una propagazione automatica degli errori delle eccezioni non gestite.
D'altra parte ho visto un sacco di codice nei progetti open source (come nell'esempio sopra) che non fa alcun controllo dei puntatori prima di usarli. Mi chiedo se qualcuno abbia delle idee sulle linee guida per quando mettere i controlli in una funzione anziché supporre che la funzione sia stata chiamata con argomenti corretti.
Sono interessato a questa domanda in generale per la scrittura del codice di produzione. Ma sono anche interessato al contesto delle interviste di programmazione. Ad esempio, molti libri di testo di algoritmi (come CLR) tendono a presentare gli algoritmi in pseudocodice senza alcun controllo degli errori. Tuttavia, sebbene ciò sia utile per comprendere il nucleo di un algoritmo, non è ovviamente una buona pratica di programmazione. Quindi non vorrei dire a un intervistatore che stavo saltando il controllo degli errori per semplificare i miei esempi di codice (come potrebbe fare un libro di testo). Ma anche io non vorrei sembrare che produca codice inefficiente con un controllo degli errori eccessivo. Ad esempio, graph_get_current_column_color
avrebbe potuto essere modificato per verificare la presenza *graph
di null, ma non è chiaro cosa farebbe se *graph
fosse null, a parte questo non dovrebbe dereferenziarlo.