2011-01-10 12 views
5

Sto sviluppando un'applicazione per iPhone che utilizza principalmente la rubrica e il database. Dopo aver recuperato circa 3000 contatti dalla rubrica, allego i tag delle stringhe ai contatti (5 per ciascuno). Sto salvando i miei tag nel database.Perdite di memoria causate da CoreFoundation Framework

Per carico scopo di test ho aggiunto 10.000 tag per l'applicazione. Ma durante il test di carico della mia applicazione, ho osservato alcune perdite di memoria che non erano correlate al codice dell'applicazione ma rappresentano un insieme di set di istruzioni. Anche Instruments ha mostrato Foundation come la biblioteca responsabile per la perdita (uso estensivo di NSString, NSDictionary, NSArray che appartiene al framework Foundation). La mia applicazione si blocca dopo 10 - 15 minuti di utilizzo. Il rapporto Crash cita, l'applicazione si è bloccata a causa della poca memoria.

Il profilo di memoria con CLANG mostra zero perdite. Come risolvo queste perdite di memoria? Queste perdite sono il vero colpevole dietro l'incidente? Sono disponibili altri strumenti per controllare le perdite di memoria?

+1

Questo potrebbe essere un problema di autorelease. Succede ancora se lo fai in lotti? Cioè, in diverse iterazioni del runloop? Forse avvolgere l'operazione con la sua piscina. – Eiko

+0

Sì, ho provato a svuotare il pool di rilascio automatico una volta che l'applicazione riceve un avviso di memoria, ma anche il drenaggio del pool non va bene. – Aditya

+0

Dovresti sapere se le perdite sono il colpevole, quanta memoria gli strumenti dicono che stai perdendo? – hooleyhoop

risposta

4

Spesso trovo che le mie fughe di notizie siano causate dalla Core Foundation (o da qualsiasi altra struttura), ma sono davvero mie. Ad eccezione del simulatore, raramente troverai perdite eccessive nei framework.

Se si apre il pannello dei dettagli a destra in Strumenti, è possibile trovare i metodi della propria app qui elencati. Questo ti darà l'indicazione di dove potrebbe provenire dal tuo codice. Una perdita può scatenare molte altre perdite e potrebbe essere necessario trovare il colpevole di livello superiore per sbarazzarsi di quelle di livello inferiore.

Non dovresti aspettarti che Clang faccia qualcosa ma trovi le perdite più ovvie. È molto utile, ma è solo un'utile aggiunta alla compilazione.

-1

cercare di fare alcuni problemi nel codice u: 1. Si prega di evitare nascondere dichiarazione come

NSString *string = [dictionary valueForKey:[dictionary2 valueForKey:@"something"]] 

codice corretto è:

NSString *key = [dictionary2 valueForKey:@"something"]; 
NSString *string = [dictionary valueForKey:key]; 
key = nil; 
  1. Cercare di evitare la dichiarazione con autorelease e locale dichiarazione come:

    NSArray * array = [array NSArray];

Se u fare questo, assicurarsi che u have:

NSArray *array = [NSArray array]; 
.... some code where array is using; 
array = nil; 

migliore idea è alloc e rilasciarlo immediatamente quando u non ha bisogno oggetto e metterlo a zero. 3. Controllare se si utilizzano setter corretti. Probabilmente l'idea migliore è evitare di usarla, secondo la mia esperienza, deallocare le perdite di inizio della classe per getter e setter, che stavano usando prima.

Se si pubblica una parte del codice u, dove si vedono le perdite maggiori (gli strumenti ti danno la possibilità di fare clic sugli oggetti trapelati e vedere il volume delle perdite nel codice di programmazione) la community può suggerire di più.

1

clang non è un controllore di perdite. Rileva solo un piccolo sottoinsieme di problemi.

Per il debug della perdita di memoria, è necessario concentrarsi sugli strumenti, in particolare sugli strumenti di allocazione degli oggetti e perdite. Assicurati di capire la differenza tra perdite e altra fonte di utilizzo della memoria alta però.

Una volta stabilito che gli oggetti perdono, utilizzare Strumenti per esaminare la traccia dello stack di allocazione (in modo che sia possibile determinare quale oggetto sia) e la cronologia di conservazione/rilascio.

Se non è una perdita, quindi suggerisco di indagare le istruzioni qui: http: //www.friday.com/bbum/2010/10/17/when-is-a-leak-not-a-leak- using-heapshot-analysis-to-find-undesirable-memory-growth/

+0

Ya ho risolto tutte le perdite causate dal framework che pensavo fossero dovute al framework, ma non lo erano..Per ora il problema è con le allocazioni ... ci sono un sacco di allocazioni fatte durante il ciclo di vita dell'app che stanno causando l'arresto anomalo dell'app dopo 10 minuti di utilizzo. – Aditya

+1

Gli Heapshots sono tuoi amici. – v01d

1

Molto probabilmente si dispone di codice che crea gli oggetti di base. Le perdite indicano il luogo di allocazione, ma generalmente è dovuto a una chiamata effettuata dal codice per creare l'oggetto. Puoi guardare la catena di chiamate in Strumenti e tornare indietro lungo la catena di chiamate fino ad arrivare al tuo codice - questo è il posto dove stai causando l'allocazione. Ora, per quella allocazione, guarda la tua gestione della memoria per quell'oggetto: lo rilascerai qualche tempo dopo?

Ci sono molti modi in cui non è possibile rilasciare le proprietà della memoria, quindi sarebbe difficile indovinare quale si potrebbe colpire. Quello che vedo quando aiuta le persone include allocare un oggetto e assegnarlo a una variabile di istanza tramite una proprietà con l'attributo retain, qualcosa come questo:

@property (retain) NSString * myString;

...

self.myString = [[NSString alloc] initWithString: @ "foo"];

l'alloc + init crea un oggetto mantenuto, il self.myString = incrementa nuovamente il conteggio di conservazione. Se codificato correttamente, il metodo dealloc rilascia la proprietà tramite uno di:

[myString release]; o self.myString = nil;

E che si occupa del retain aggiunto con self.myString = ma NON si occupa della conservazione dalla creazione. Soluzioni, UNA delle seguenti:

myString = [[NSString alloc] initWithString: @ "foo"]; // non chiama il metodo setter, quindi non mantiene alcuna assegnazione, ma non chiama il setter che potrebbe essere cattivo se setter non banale.

self.myString = [[[NSString alloc] initWithString: @ "foo"] autorelease];

autorelease rilascia l'alloc + init retain.

Ora, naturalmente, questo è un esempio inventato perché si sarebbe probabilmente davvero usare:

self.myString = [NSString stringWithString: @ "foo"];

che è un metodo di classe che restituisce una stringa autorizzata ed evita il problema. Ma l'idea è di mostrare un semplice esempio per spiegare questo tipo di problema.

Ci sono molti altri modi per non rilasciare correttamente la memoria, ma il consiglio di risalire la catena di chiamata fino ad arrivare al codice è la strada da seguire dove si sta attivando l'allocazione della memoria e quindi puoi capire perché non lo stai rilasciando correttamente.