Domanda

Sembra che io non ho capito la gestione della memoria in Objective C ... sigh.

Ho il codice seguente (si noti che nel mio caso, placemark.thoroughfare e placemark.subThoroughfare sono entrambi pieni di dati validi, quindi entrambe le if-condizioni saranno TRUE

item è legata ad una ManagedObjectContext. Le variabili gestite in item quali place hanno setter / getter creati con @dynamic. Così, la dichiarazione è

@property (nonatomic, retain) NSString *place;
@dynamic place;

Più tardi nel codice, nel ReverseGeocoderDelegate, accedo che:

- (void)reverseGeocoder:(MKReverseGeocoder *)geocoder didFindPlacemark:(MKPlacemark *)placemark {

if (placemark.thoroughfare) {
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];        
} else {
    [item.place release];
    item.place = @"Unknown Place";
}
if (placemark.thoroughfare && placemark.subThoroughfare) {
// *** problem is here ***
    [item.place release];
    item.place = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}

Se non rilasciare item.place alla posizione indicata nel codice, strumenti ci trova una perdita di memoria. Se lo faccio, il programma si blocca non appena provo ad accedere item.place di fuori del metodo offendere.

Tutte le idee?

È stato utile?

Soluzione

Prima di tutto, vorrei cambiare la logica in questo modo:

NSString *newPlace = nil;

if (placemark.thoroughfare && placemark.subThoroughfare) {
    newPlace = [NSString stringWithFormat:@"%@ %@", placemark.thoroughfare , placemark.subThoroughfare];
}
else {
    if (placemark.thoroughfare) {
        newPlace = [NSString stringWithFormat:@"%@ ", placemark.thoroughfare];
    }
    else {
        newPlace = @"Unknown Place";
    }
}

item.place = newPlace;    // Either nil of valid string can be assigned to

Utilizzando immissione in puntatore semplicemente ri-inizializzazione non è così raccomandato da molti. Non dovete fare questo se fosse per risparmiare un po 'di memoria.

La logica precedente non rilasciando due volte . Ciò che fa di rilascio inizialmente è semplicemente decremento retainCount. Se è 0, allora l'oggetto viene deallocato. L'oggetto non sarà deallocata fino alla sua retainCount è 0.

Assumendo che il l'elemento ha la proprietà mantenere e dal stringa ritorna stringWithFormat: autoreleased, così, alla seconda uscita, si stava tentando di liberare quello che stava per essere autoreleased comunque.

Il modo migliore per eliminare un oggetto più volte è semplicemente assegnando nil ad esso.

Altri suggerimenti

Un punto di partenza potrebbe essere quello di ri-leggere di proprietà, perché non c'è bisogno di fare `[item.place rilasciare]' ovunque. Così è possibile rimuoverli. Il codice di dinamica creata dal runtime per consentire che la proprietà automaticamente maniglie rilasciando nulla precedentemente assegnato ad esso.

Inoltre, il [NSString stringWithFormat:... crea un oggetto autorelease (non so se si sapeva che :-) Il che significa che se si dove gestire manualmente la memoria per una variabile (non una proprietà), allora si dovrà mantenere / rilasciarlo. Ma perché si sta utilizzando le proprietà, non è necessario.

Non riesco a capire perché gli strumenti è trovare una perdita di memoria. Forse un codice più in alto è a che fare con esso. Per esempio se si è andato item.place = [NSString alloc] initWith...]; allora penso che avrebbe bisogno di esso.

L'incidente ho il sospetto di essere a causa dei rilasci causando mantenere i conteggi pari a zero e innescando errori di accesso cattivi exec.

La speranza che aiuta.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top