2013-07-22 26 views
6

Zostałem poproszony o wyczyszczenie niektórych błędów Clang w bazie kodu. Jestem nowicjuszem w rozwoju iPhone'a i Celu C, ale większość problemów jest banalnych ... ten jednak mnie denerwuje, kiedy jestem pewien, że jest to coś krępującego.Objective-C: Zmienna instancji używana, gdy "self" nie jest ustawione ... ale jest

z klasy ZAttributedString:

- (id)initWithAttributedString:(ZAttributedString *)attr { 
    NSParameterAssert(attr != nil); 
    if ((self = [super init])) { 
     _buffer = [attr->_buffer mutableCopy]; 
     _attributes = [[NSMutableArray alloc] initWithArray:attr->_attributes copyItems:YES]; 
    } 
    return self; 
} 

Ostrzeżenie dzyń jest „zmienna instancji wykorzystywane podczas gdy«ja»nie jest ustawiony na skutek«[SUPER lub jaźni] Init ...]», z dereferencing atrybutu _buffer atr za podświetlonego

Jeśli to pomoże, ostrzeżenie wydaje się również, aby wspomnieć, że problem występuje, gdy dzwonisz z tej metody.

- (id)copyWithZone(NSZone *)zone { 
    return [(ZAttributedString *)[ZAttributedString allocWithZone:zone] initWithAttributedString:self]; 
} 

Can Proszę mi wyjaśnić, kim dokładnie jest ta wada?

TIA!

Odpowiedz

4

Nie używaj ->, aby uzyskać dostęp do zmiennych instancji, , szczególnie, gdy ivar pochodzi z innego obiektu.

Wykonaj:

_buffer = [[attr string] mutableCopy]; 

samo dotyczy tego bolesnego attr->_attributes. Wygląda na to, że ZAttributString exposes ma atrybuty` jako właściwość w nagłówku prywatnym.


To ostrzeżenie kompilatora wydaje, co najwyżej optymistyczne, całkowicie mylące i, prawdopodobnie, bardzo źle w opisie. Zgłoszenie błędu, który by to wyjaśnił, byłoby użyteczne.


Uwaga To @ maddy twierdzenie, że za pomocą -> aby uzyskać dostęp do zmiennych instancji bezpośrednio w ciągu attr przeszedł jak to działa jak konstruktora kopii jest niepoprawna.

Przychodzące attr może być przypadek ZAttributedString lub wystąpienie podklasy lub bardzo instancja jakiejkolwiek klasy, który implementuje samego interfejsu jak ZAttributedString. Zatem naprawdę musisz przejść przez akcesory, aby zagwarantować, że przechwytujesz poprawny stan.

Teraz, jako szczegół realizacji, ZAttributedString mógł wymagają że instancja przychodzące być non-podklasy instancja ZAttributedString, ale powinno wykorzystywać isMemberOfClass: dochodzić tego wymogu (i, proszę, nie rób tego).

Jedynym miejscem, w którym bezpośredni dostęp do ivar jest czasem wykorzystywany do pobierania stanu z innego obiektu, jest implementacja copyWithZone:, ale jest to niezwykle kruche i często prowadzi do błędnego zachowania. W rzeczywistości, copyWithZone: (poza różnymi klasami wartości zgodnych z plistem) był pełen kruchości i źródłem wielu wielu błędów.

+3

Właściwie ten kod pochodzi z klasy 'ZAttributString', więc jest całkowicie poprawne użycie' -> 'do dostępu do ivars z innej instancji tej samej klasy. Jest to odpowiednie w takim kodzie, gdy zasadniczo tworzysz "konstruktora kopiowania". – rmaddy

+1

Niezupełnie, nawet w tym przypadku. * Jeśli * była to sama metoda '-copy', to * może * (nawet to jest naprawdę ostra krawędź w historii ObjC -' NSCopyObject() 'nie spowodowało końca bólu). Ale nie w DI. Klasa może mieć logikę dla modułów pobierających, które coś wykonują, a ta wbudowana instancja może bardzo prawdopodobnie być podklasą z nieznanymi zachowaniami. – bbum

+0

@bbum: "Przychodzące attr może być instancją ZAttributedString lub instancją podklasy" self "może również być instancją podklasy, więc przez ten argument nie można uzyskać dostępu do zmiennych instancji, co oczywiście nie jest prawdą. – user102008

2

Wygląda na to, że widzisz dokładnie ten sam błąd, co: "[Bug 15092] New: static analyzer false positive: reports instance variable used while 'self' is not set to the result of [(super or self)] init". Ma bardzo podobny kod dołączony do odtworzenia błędu.

Po uruchomieniu tego kodu w Xcode 4.6.3 można sprawdzić, czy wyświetla on to samo fałszywe ostrzeżenie.

enter image description here

Błąd został rozwiązany z comment:

Zostało to poprawione w bagażniku, a przynajmniej w większości stały - nadal istnieje kilka przypadków, w których krawędź ostrzeżenie będzie ogień, ale nie twój projekt.

(Dave, na razie wszystko z głównych inżynierów analizatora działają na Apple, więc nie ma rzeczywistej potrzeby złożyć duplikatów. W LLVM ludzie, którzy nie pracują w Apple nie mieć dostęp do Apple Clang, których statki z Xcode i tej poprawki nie uczynił Xcode 4.6. można również uzyskać nowsze sprawdzania buduje od http://clang-analyzer.llvm.org)

Jak widać problem został rozwiązany, ale nadal obecne w Xcode 4.6. Trzymaj się następnej wersji Xcode i ostrzeżenie o analizatorze powinno zniknąć.

+0

Dziękujemy za wyśledzenie błędu llvm. Przydatny! – bbum