2009-07-27 29 views
46

Wciąż dostaję błędy brzękiem na następnej typu kodu i nie mogę zrozumieć, dlaczego są one błędne lub jak rozwiązać ich zadowoleniu dzyń:Błąd połączenia z "Potencjalnym dereferencją zerową".

+ (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; 
    } 
} 

Pomijając całkowicie-contrived charakter celu przykład (który Clang nie sprzeciwił się, więc jest to wystarczająco ilustrujące), Clang zaciąga się w linii przypisania błędu z następującym zastrzeżeniem:

Potencjalny dereferencja zerowa. Zgodnie ze standardami kodowania w 'Tworzenie i zwracanie NSError obiektów' parametr "błąd" może być pusty.

Lubię mieć nieskazitelny raport Clang. Czytałem cytowany dokument i nie widzę sposobu na zrobienie tego, czego się spodziewano; Sprawdziłem biblioteki kakao o otwartym kodzie źródłowym i wydaje się, że jest to powszechny idiom. Jakieś pomysły?

Odpowiedz

95

Sposób zrobienia tego, co jest oczekiwane, przedstawiono na listingu 3-5 w tym dokumencie. Z kodem Przykład:

+ (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, nie mogę uwierzyć, że to przegapiłem. Dzięki! – bbrown

+0

Użyłem miliona razy 'if (error) * error = ...' zamiast, bez żadnych awarii lub błędów/ostrzeżeń analizatora. Czy mogę iść dalej tą drogą? –

+0

Tak, jawna równoważność zerowego wskaźnika do 0 i fałsz jest czymś, co obiektywne C zachowane od zwykłego starego C. Ja osobiście uważam, że jest to zły styl, ale tak, możesz po prostu użyć 'if (error)' jeśli naprawdę chcesz. –

16

Konwencja Kakao jest to, że wartość zwracana powinny wskazywać sukces lub niepowodzenie (w tym przypadku należy zwrócić nil do awarii), a błąd jest wypełnione z dodatkowymi informacjami, ale tylko wtedy, gdy dzwoniący żąda tego.

Innymi słowy

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

i

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

są zarówno ważne sposoby na wywołanie metody. Tak więc treść metody powinna zawsze sprawdzać wartość NULL:

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

Właściwie, jeśli statyczny analizator klang nie będzie narzekał na twój drugi snippit, to zgłoszę błąd :-) –

+0

Czy odwołujesz się do fragmentu, gdzie NULL jest przekazywana dla błędu param? Jest to udokumentowany wzorzec użycia NSError. Zobacz . –

+0

Gdybym mógł zaznaczyć dwie odpowiedzi, zrobiłbym to. Dziękuję za wyjaśnienie kontekstu, w którym to może się stać! – bbrown

Powiązane problemy