Pregunta

Cada vez que llamo a este método mi NSMutableData tiene una fuga y no puedo averiguar cómo conectarlo. La cuenta de retención de los datos se incrementa en uno después de que el decodificador se asigna e inicializa y no tengo idea de por qué. Estoy atascado con una cuenta de retención de 2 al final del método e intentar liberarlo provoca un bloqueo de la aplicación.

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;


    theData = [NSData dataWithContentsOfFile:inFile];

    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

    venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

    [decoder finishDecoding];

    [decoder release];
}
¿Fue útil?

Solución

Sugeriría reemplazar esta línea:

venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

con:

ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
self.venueIOList = decodedList;

Esto hace que la gestión de memoria de decodedList sea clara. Se considera la mejor práctica asignar variables de instancia utilizando un método de acceso (excepto en los métodos de inicio). En su implementación actual, si alguna vez invoca readVenueArchiveFile: por segunda vez en el mismo objeto, perderá (como ocurrirá si decodedList ya tiene un valor). Además, puede poner la lógica de copia en su método de acceso y olvidarse de ella en lugar de tener que recordar mutableCopy cada vez que asigne un nuevo valor (¿suponiendo que haya una buena razón para hacer una copia mutable?).

Otros consejos

Reducción de la huella de memoria máxima

En general, se considera una buena práctica evitar la generación de objetos lanzados automáticamente.

[La mayor parte de este párrafo se modificó de esta pregunta .] Desde que por lo general (1) no tienen control directo sobre su vida útil, los objetos lanzados automáticamente pueden persistir durante un tiempo comparativamente largo y aumentar innecesariamente la huella de memoria de su aplicación. Si bien en el escritorio, esto puede tiene poca importancia, en plataformas más restringidas puede ser un problema importante. Por lo tanto, en todas las plataformas, y especialmente en las plataformas más restringidas, donde sea posible, no se recomienda el uso de métodos que conduzcan a la publicación automática de objetos y, en cambio, se recomienda que utilicen el patrón alloc / init.

Sugeriría reemplazar esto:

theData = [NSData dataWithContentsOfFile:inFile];

con:

theData = [[NSData alloc] initWithContentsOfFile:inFile];

luego al final del método agrega:

[theData release];

Esto significa que theData se desasignará antes de que salga el método. Deberías terminar con:

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;

    theData = [[NSData alloc] initWithContentsOfFile:inFile];
    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
    ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
    self.venueIOList = decodedList;
    [decoder finishDecoding];
    [decoder release];
    [theData release];

}

Esto aclara la semántica de administración de memoria y recupera la memoria lo más rápido posible.

(1) Puede tomar el control utilizando sus propios grupos locales de autorelease. Para obtener más información sobre esto, consulte Guía de programación de gestión de memoria de Apple .

No se preocupe por retener cuentas, preocuparse por el equilibrio dentro de un método. Lo que está haciendo en este método parece correcto, asumiendo que venueIOList es una variable de instancia.

Para ampliar un poco mi respuesta: el desarchivador podría retener sus datos durante la operación de desarchivar, y luego enviar los datos -autorelease cuando se haga en lugar de -release . Ya que eso no es algo que hiciste , no es algo que tengas que preocuparte.

La mejor fuente para la iluminación de la gestión de memoria relacionada con refcount es todavía, IMO, " Hold Me, Use Me, Free Me " de Stepwise.

Tu código es correcto; no hay pérdida de memoria.

theData = [NSData dataWithContentsOfFile:inFile];

es equivalente a

theData = [[[NSData alloc] initWithContentsOfFile:inFile] autorelease];

En este punto, los datos tienen un recuento de referencia de 1 (si es menor, se desasignará). El número de referencia se reducirá automáticamente en algún momento en el futuro por el conjunto de autorelease.

decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

El objeto decodificador mantiene una referencia a theData que incrementa su recuento de referencias a 2.

Una vez que el método vuelve, el grupo de autorelease disminuye este valor a 1. Si libera los Datos al final de este método, el recuento de referencia se convertirá en 0, el objeto se desasignará y su aplicación se bloqueará cuando intente utilízalo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top