2013-07-22 12 views
6

Sono stato incaricato di eliminare alcuni errori di Clang in un code base. Sono molto nuovo allo sviluppo dell'iPhone e all'Obiettivo C, ma ho trovato la maggior parte dei problemi banali ... questo mi ha comunque bloccato, quando sono sicuro che sia qualcosa di imbarazzante.Objective-C: variabile di istanza utilizzata mentre 'self' non è impostata ... ma è

da una classe 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; 
} 

L'avvertimento è clang "variabile istanza utilizzato po 'sé' non è impostato il risultato di '[super o auto] init ...]', con il dereferencing dell'attributo _buffer di attr essere evidenziata

Se aiuta, l'avvertimento sembra anche di ricordare che il problema si trova quando si chiama questo metodo:.

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

Can Qualcuno, per favore, spiegami qual è esattamente il difetto qui?

TIA!

risposta

4

Non utilizzare -> per accedere alle variabili di istanza, in particolare quando l'ivar proviene da qualche altro oggetto.

fare questo:

_buffer = [[attr string] mutableCopy]; 

Lo stesso vale per quel brutto attr->_attributes. Apparentemente, ZAttributedString exposes attributi` come proprietà nell'intestazione privata.


Questo avviso del compilatore sembra, per lo più ottimista, del tutto fuorviante e, probabilmente, del tutto sbagliato nella descrizione. Presentare un bug per avere quello chiarito sarebbe utile.


noti che @ di maddy rivendicazione che usando -> accedere alle variabili di istanza direttamente nella stringa attr passata come agisce come un costruttore di copia non è corretto.

L'entrata attr può essere un'istanza ZAttributedString o un'istanza di una sottoclasse o, in realtà, un'istanza di qualsiasi classe che implementa la stessa interfaccia ZAttributedString. Quindi, davvero deve passare attraverso gli accessor per garantire che stai acquisendo lo stato corretto.

Ora, come un dettaglio di implementazione, ZAttributedString potrebbe richiedono che l'istanza in entrata sia un'istanza non sottoclasse di ZAttributedString, ma dovrebbe utilizzare isMemberOfClass: per affermare tale obbligo (e, per favore, non farlo).

L'unico punto in cui l'accesso diretto di ivar viene talvolta utilizzato per estrarre lo stato da un altro oggetto è nell'implementazione di copyWithZone:, ma che è estremamente fragile e spesso causa comportamenti malfunzionanti. Infatti, copyWithZone: (al di fuori delle varie classi di valore compatibili plist) è stato ricco di fragilità e la fonte di molti molti bug.

+3

In realtà, questo codice proviene dalla classe 'ZAttributedString', quindi è perfettamente corretto utilizzare' -> 'per accedere a ivars da un'altra istanza della stessa classe. Questo è appropriato in tale codice quando si sta fondamentalmente creando un "costruttore di copie". – rmaddy

+1

Non proprio corretto, anche in questo caso. * Se * fosse il metodo '-copy' stesso, allora * forse * (anche se questo è davvero un problema nella storia di ObjC -' NSCopyObject() 'non ha causato alcuna fine al dolore). Ma non nel DI. La classe può avere una logica sui getter che fanno qualcosa e questa istanza in-bound potrebbe molto probabilmente essere una sottoclasse con comportamenti sconosciuti. – bbum

+0

@bbum: "L'attr in arrivo può essere un'istanza ZAttributedString o un'istanza di una sottoclasse" self "potrebbe anche essere un'istanza di una sottoclasse, quindi con tale argomento non è possibile accedere alle variabili di istanza, che ovviamente non è vero. – user102008

2

Sembra che tu stia vedendo lo stesso identico bug di questo: "[Bug 15092] New: static analyzer false positive: reports instance variable used while 'self' is not set to the result of [(super or self)] init". Ha un codice molto simile allegato per riprodurre il bug.

Se si esegue quel codice in Xcode 4.6.3, è possibile verificare che assegni lo stesso falso avviso.

enter image description here

Il bug è stato risolto con l'comment:

Questo è stato risolto in tronco, o almeno in gran parte risolto - ci sono ancora un qualche margine casi in cui l'avviso sarà sparare, ma non il tuo progetto.

(Dave, per ora tutti i principali ingegneri analizzatore funzionano in Apple, quindi non c'è alcuna reale necessità di archiviare i duplicati. La gente LLVM che non lavorano in Apple non hanno accesso ad Apple Clang, che viene fornito con Xcode, e questa correzione non ha fatto Xcode 4.6. è inoltre possibile ottenere più recente checker costruisce da http://clang-analyzer.llvm.org)

Come si può vedere il bug è stato risolto, ma ancora presenti in Xcode 4.6. Aspetta la prossima versione di Xcode e l'avviso dell'analizzatore dovrebbe sparire.

+0

Grazie per aver rintracciato il bug di llvm. Utile! – bbum

Problemi correlati