2009-07-27 14 views
46

continuo a ricevere errori clangore del seguente tipo di codice e io non riesco a capire perché sono errate o il modo di risolverli con soddisfazione di Clang:Clang Error on "Potenziale null dereference."

+ (NSString *)checkForLength: (NSString *)theString error: (NSError **)error { 
    BOOL hasLength = ([theString length] > 0); 
    if (hasLength) return theString; 
    else { 
     *error = [NSError errorWithDomain:@"ErrorDomain" code:hasLength userInfo:nil]; 
     return nil; 
    } 
} 

Lasciando da parte la natura del tutto-artificiosa del esempio (a cui Clang ha fatto obiezioni in modo che sia sufficientemente illustrativo), Clang esita nella riga di assegnazione degli errori con la seguente obiezione:

Potenziale dereferenziazione nulla. Secondo gli standard di codifica in "Creazione e restituzione di oggetti NSError", il parametro "errore" potrebbe essere nullo.

Mi piace avere un rapporto Clang incontaminato. Ho letto il documento citato e non riesco a vedere un modo per fare ciò che ci si aspetta; Ho controllato alcune librerie Cocoa open source e questo sembra essere un idioma comune. Qualche idea?

risposta

95

Il modo per fare ciò che è previsto è mostrato nel listato 3-5 in quel documento. Con il codice di esempio:

+ (NSString *)checkForLength: (NSString *)theString error: (NSError **)error { 
    BOOL hasLength = ([theString length] > 0); 
    if (hasLength) return theString; 
    else { 
     if (error != NULL) *error = [NSError errorWithDomain:@"ErrorDomain" code:hasLength userInfo:nil]; 
     return nil; 
    } 
} 
+1

Ugh, non posso credere di averlo perso. Grazie! – bbrown

+0

Ho usato un milione di volte "if (error) * error = ...", invece, senza crash o errori/avvisi dell'analizzatore. Posso andare avanti così? –

+0

Sì, l'equivalenza esplicita di un puntatore nullo a 0 e falso è qualcosa che l'obiettivo C trattiene dalla semplice vecchia C. Personalmente ritengo che sia uno stile pessimo, ma si può semplicemente usare "if (errore)" se proprio lo si vuole. –

16

La convenzione di cacao è che il valore di ritorno dovrebbe indicare il successo o il fallimento (in questo caso, si torna a zero per il fallimento) e l'errore viene riempito con informazioni aggiuntive, ma solo quando la il chiamante lo richiede.

In altre parole

NSError *error = nil; 
NSString *result = [self checkForLength: aString error: &error]; 

e

NSString *result = [self checkForLength: aString error: NULL]; 

sono entrambi modi validi per richiamare il metodo. Quindi il corpo del metodo dovrebbe sempre controllare un parametro di errore NULL:

if (error != NULL) 
    *error = ...; 
+0

In realtà, se l'analizzatore clang statico non si lamenta del tuo secondo snippit, inserirò un bug :-) –

+0

Ti riferisci allo snippet dove viene passato NULL per l'errore param? Questo è un modello documentato per l'utilizzo di NSError. Vedi . –

+0

Se avessi potuto contrassegnare due risposte, lo avrei fatto. Grazie per aver spiegato il contesto in cui potrebbe accadere! – bbrown

Problemi correlati