2011-12-29 10 views
5

Sto utilizzando il KeyChainItemWrapper dal codice di esempio di Apple per memorizzare password utente per l'autenticazione, ma quando io lo chiamo per impostare la password:Perdita di memoria in iOS KeychainItemWrapper

[keychain setObject:passwordField.text forKey:(id)kSecValueData]; 

E dribbla le perdite di memoria in tutta la mia camicia . Il problema a quanto pare risale alla linea 274 in KeyChainItemWrapper.m, che è questo:

if (SecItemCopyMatching((CFDictionaryRef)genericPasswordQuery, (CFTypeRef *)&attributes) == noErr) 
{ 

Come potrei risolvere questo problema, e dovrei essere più attenti quando si lavora con il codice di esempio di Apple in futuro?

Nota: potrei pubblicare più codice, ma ho ridotto il problema a questa linea utilizzando Strumenti e il codice di esempio completo è prontamente disponibile per qualsiasi sviluppatore.

risposta

5

Guardando il codice per KeyChainItemWrapper, sono d'accordo che questa linea è una perdita di memoria. Hanno perso il [attributes release] alla fine di writeToKeychain. Vedi tutte le altre chiamate a SecItemCopyMatching() in questo file per esempi di come rilasciano correttamente l'oggetto restituito per riferimento.

Vorrei utilizzare il collegamento "È buono, ma ..." in fondo a questa pagina per notare l'errore.

+0

Questo era esattamente il problema. Basta aggiungere [rilascio attributi]; alla fine della funzione spine che collegano. Questo bug è stato segnalato ad Apple come suggerito. – Serendipity

+1

Wow: per quanto riguarda il codice di esempio, penso che KeychainItemWrapper sia tra i peggiori là fuori! autoreleases in tutto il mondo, almeno 2 perdite di memoria conosciute, compreso il precedente, e un altro che inizializza portachiavi ItemData ... – npellow

+0

npellow, cosa c'è di sbagliato con autoreleases? Hanno appena rilasciato a un certo punto.Apple li usa frequentemente. In effetti, è come vogliono che noi programmiamo –

0

Ho trovato un'altra perdita in - (void) resetKeychainItem.

Dovrebbe essere

self.pKeychainItemData = [[[NSMutableDictionary alloc] init] autorelease];.

+2

perché non 'self.pKeychainItemData = [Dizionario NSMutableDictionary]?'? Tanto più pulito ... –

3

L'analisi statica segnala una perdita potenziale di un oggetto nel metodo resetKeychainItem, riga 191, di KeyChainItemWrapper.m. Sorprendentemente, non riporta una potenziale perdita nell'area sopra indicata, sebbene abbia aggiunto la versione dell'oggetto come suggerito, e per correttezza.

Ecco il codice con la perdita stati segnalati:

- (void)resetKeychainItem 
{ 
    ... 
    // Default attributes for keychain item. 
    [keychainItemData setObject:@"" forKey:(id)kSecAttrAccount]; // <-- Potential leak of an object 
    [keychainItemData setObject:@"" forKey:(id)kSecAttrLabel]; 
    [keychainItemData setObject:@"" forKey:(id)kSecAttrDescription]; 

    // Default data for keychain item. 
    [keychainItemData setObject:@"" forKey:(id)kSecValueData]; 
} 

Questo problema si riferisce il bilancio stringa vuota @ "". Ho provato una varietà di implementazioni di codice per provare a "risolvere" questo problema, ma nulla sembra funzionare.

Si tratta di un falso positivo?

Aggiornamento: Subito dopo la pubblicazione mi sono reso conto che è possibile fare doppio clic sull'avviso per tracciare l'errore.

Questo avviso viene attribuita alla linea di sopra di esso per l'assegnazione del dizionario:

if (!keychainItemData) 
{ 
    self.keychainItemData = [[NSMutableDictionary alloc] init]; 
} 

ho cambiato il codice di seguito:

if (!keychainItemData) 
{ 
    self.keychainItemData = [[[NSMutableDictionary alloc] init] autorelease]; 
} 

L'avvertimento analizzatore non è più presente.