2009-03-23 13 views
6

Ho un'app per iPhone che sta ricevendo avvisi di memoria e quindi sto cercando di trovare perdite, fare un uso più efficiente della memoria, ecc., Con l'aiuto di Instruments. Tra le altre cose, sto cercando di eliminare qualsiasi oggetto autoreleased e di sostituirlo con oggetti alloc/init/release manuali. Tuttavia, alcune chiamate API non sembrano avere una versione "init" (vedi il codice sotto). Ho certamente avuto alcune incomprensioni di base:Utilizzo degli strumenti Perdite e oggetto Alloc: Gli oggetti autoreleased vengono conteggiati come perdite?

  1. Se Sono mettere in 'l'API e tornare oggetti essenzialmente autoreleased, possono questi oggetti visualizzati come perdite nel Instruments? Sembra che io veda questo comportamento in Strumenti.

  2. Se sì a 2, dovrei semplicemente ignorare se non esiste un'alternativa "non autorelease" e sto usando un'API di cui ho bisogno? Inoltre, se questo codice viene chiamato molto, dovrei ripensare completamente l'algoritmo?

Ecco un codice di utilità dalla mia applicazione che viene chiamato molto. Fondamentalmente determina se due date sono significativamente 'uguali'. Ho lasciato nel codice commentato in modo da poter vedere i tipi di miglioramenti che sto seguendo nella mia base di codice - questo DID ridurre le perdite di memoria quando successivamente eseguito in strumenti come ho iniziato a creare manualmente il NSDate (e rilasciare) che ha aiutato. Tuttavia, ho ancora gli oggetti componenti data che credo siano perdite ... ma è una chiamata API (scusate per la formattazione del codice, ma io non riesco a migliorarlo su SO):

+ (BOOL)isDayEqualToDay:(NSDate*)date anotherDate:(NSDate*)anotherDate 
{ 

    NSCalendar *cal = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar]; 
    //NSCalendar *cal; 
    NSDateComponents *componentsFromDate, *componentsFromAnotherDate; 
    NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;  
    //cal = [NSCalendar currentCalendar]; 
    componentsFromDate = [cal components:unitFlags fromDate:date]; 
    componentsFromAnotherDate = [cal components:unitFlags fromDate:anotherDate]; 

    BOOL bDatesEqual = ([componentsFromDate year] == [componentsFromAnotherDate year] && 
         [componentsFromDate month] == [componentsFromAnotherDate month] && 
         [componentsFromDate day] == [componentsFromAnotherDate day]); 

    [cal release]; 

    return bDatesEqual; 

    /* 
    return (
     [componentsFromDate year] == [componentsFromAnotherDate year] && 
     [componentsFromDate month] == [componentsFromAnotherDate month] && 
     [componentsFromDate day] == [componentsFromAnotherDate day] 
    );*/ 
} 

penso i componentiFromDate e componentsFromAnotherDate vengono visualizzati come perdite ma solo oggetti restituiti essenzialmente da una chiamata API NSData (autoreleased). Non so cos'altro potrei davvero fare per rendere questo più efficiente e sto mettendo in discussione la mia comprensione di come utilizzare gli strumenti. Suggerimenti?

risposta

4

L'oggetto Autoreleased non dovrebbe apparire come perdite di memoria. A volte le API hanno perdite di memoria al loro interno. Dovresti presentare una segnalazione di bug con apple. Le nuove classi come NSCalendar e NSDateComponenets sono particolarmente sospette.

Per quanto riguarda il mantenimento rispetto all'autelease, la regola generale è che non importa se non si è in un ciclo stretto. In tal caso, se il ciclo stretto si muove molte migliaia di volte senza che l'evento se ne vada, significa che non si "pulisce" mai il pool di autorelease.

3

Quando si utilizzano elementi come GCD, esiste un pool di autorelease, ma non si ha modo di sapere quando (se mai) il pool di autorelease predefinito viene scaricato. Se sei convinto che gli oggetti non rilasciati non vengano rilasciati, assicurati di aver compreso la API di thread che stai utilizzando. Se la memoria mi serve correttamente chiamate GCD (dispatch_async) ordinano i pool di autorelease per te, MA il drenaggio effettivo del pool può richiedere molto tempo. D'altra parte, NSOperations ti consente di creare il pool di autorelease.

Ho visto il rilevamento di perdite di memoria in Strumenti che si basano su intervalli di 10 secondi provocano falsi avvisi di perdita di mem a causa di un ritardo prolungato prima del drenaggio di un pool di rilascio automatico. In modo da provare avvolgendo il codice incriminato in:

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
... [your code] ... 
[pool drain]; 

Mi consiglia di non tentare di sostituire tutte le autoreleases con le versioni manuali. L'uso dei risultati di autorelease in un numero di chiamate di ritenzione/rilascio ballate in un punto. Creare un oggetto e quindi autorizzarlo immediatamente previene molti bug di memoria secondo me. Veloce, facile. Dimenticherai di rilasciare roba quando usi le chiamate di rilascio manuali. Soprattutto le condizioni di errore sono complicate quando si eseguono rilasci manuali.

Fare da soli una piscina offre un maggiore controllo e durante l'assegnazione di un lavoro intensivo a volte può essere utile creare e drenare le proprie piscine. Ma come sempre, prova e prova, non fare ipotesi.

+0

Sembra che non ci sia modo di utilizzare gli strumenti per eseguire il debug di GDC. C'è forse un altro modo? –