Question

Chaque fois que j'appelle cette méthode, mon NSMutableData présente une fuite et je ne vois pas comment le brancher. le nombre de retenues de theData est augmenté de un après l'attribution et l'initialisation du décodeur et je ne sais pas pourquoi. Je suis coincé avec un nombre de retenues de 2 à la fin de la méthode et j'essaie de la libérer, ce qui provoque un blocage de l'application.

- (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];
}
Était-ce utile?

La solution

Je suggérerais de remplacer cette ligne:

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

avec:

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

Ceci rend la gestion de la mémoire de decodedList claire. La meilleure pratique consiste à affecter des variables d'instance à l'aide d'une méthode d'accès (sauf dans les méthodes init). Dans votre implémentation actuelle, si vous invoquez une seconde fois readVenueArchiveFile: sur le même objet, vous ferez fuite (comme vous le ferez si decodedList déjà a une valeur). De plus, vous pouvez insérer la logique de copie dans votre méthode d'accès et l'oublier au lieu de devoir vous souvenir de mutableCopy chaque fois que vous affectez une nouvelle valeur (en supposant qu'il y ait une bonne raison de faire une copie mutable de toute façon?).

Autres conseils

Réduction de l'empreinte mémoire maximale

En général, il est recommandé de ne pas générer d'objets auto-libérés.

[La majeure partie de ce paragraphe a été modifiée à partir de cette question .] Depuis votre En règle générale (1) ne contrôlent pas directement leur durée de vie, les objets auto-libérés peuvent persister relativement longtemps et augmenter inutilement l'encombrement de la mémoire de votre application. Sur le bureau, cela peut avoir peu d'importance, sur des plates-formes plus contraintes, cela peut constituer un problème important. Par conséquent, sur toutes les plates-formes, et en particulier sur les plates-formes plus contraintes, il est fortement déconseillé, dans la mesure du possible, d’utiliser des méthodes qui conduiraient à la suppression automatique d’objets, mais plutôt d’utiliser le modèle alloc / init.

Je suggérerais de remplacer ceci:

theData = [NSData dataWithContentsOfFile:inFile];

avec:

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

puis à la fin de la méthode, ajoutez:

[theData release];

Cela signifie que theData sera désalloué avant la sortie de la méthode. Vous devriez vous retrouver avec:

- (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];

}

Ceci clarifie la sémantique de la gestion de la mémoire et récupère la mémoire aussi rapidement que possible.

(1) Vous pouvez prendre le contrôle en utilisant vos propres pools de libération automatique locaux. Pour plus d'informations à ce sujet, voir Guide de programmation de gestion de la mémoire d’Apple .

Ne vous inquiétez pas du nombre de retenues, de l’équilibre au sein d’une méthode. Ce que vous faites dans cette méthode semble correct, en supposant que venueIOList est une variable d'instance.

Pour approfondir un peu ma réponse: Unarchiver peut conserver vos données pendant l'opération unarchive, puis envoyer les données -autorelease à la place de -release . Puisque ce n'est pas quelque chose que vous avez fait, ce n'est pas quelque chose dont vous devez vous soucier.

La source ultime d’éveil à la gestion de la mémoire liée à refcount est toujours, OMI, " Tiens-moi, utilise-moi, libère-moi de Stepwise.

Votre code est correct. il n'y a pas de fuite de mémoire.

theData = [NSData dataWithContentsOfFile:inFile];

est équivalent à

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

À ce stade, theData a un nombre de références égal à 1 (s'il était inférieur, il serait désalloué). Le décompte de références sera automatiquement décrémenté à un moment donné par le pool de libération automatique.

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

L'objet décodeur conserve une référence à theData qui incrémente son compte de références à 2.

Après le retour de la méthode, le pool de libération automatique décrémente cette valeur à 1. Si vous libérez theData à la fin de cette méthode, le compte de références devient 0, l'objet est libéré, et votre application se bloque lorsque vous essayez de utilisez-le.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top