Question

Mettre à jour : j'ai modifié le code, mais le problème persiste ...

Bonjour à tous,
C'est mon premier post ici - j'ai trouvé cet endroit une excellente ressource pour résoudre beaucoup de mes questions. Normalement, je fais de mon mieux pour réparer quoi que ce soit par moi-même, mais cette fois, je ne sais vraiment pas ce qui ne va pas, alors j'espère que quelqu'un pourra m'aider.
Je construis une application iPhone qui analyse deux fichiers XML à l'aide de TouchXML. J'ai une classe XMLParser, qui se charge de télécharger et d'analyser les résultats. Je reçois des fuites de mémoire lorsque j'analyse plusieurs fois un fichier XML avec la même instance de XMLParser. Voici l'un des extraits d'analyse (uniquement la partie pertinente):

for(int counter = 0; counter < [item childCount]; counter++) {  
        CXMLNode *child = [item childAtIndex:counter];
        if([[child name] isEqualToString:@"PRODUCT"]) 
        {
            NSMutableDictionary *product = [[NSMutableDictionary alloc] init];
            for(int j = 0; j < [child childCount]; j++) {
                CXMLNode *grandchild = [child childAtIndex:j];
                if([[grandchild stringValue] length] > 1) {
                    NSString *trimmedString = [[grandchild stringValue] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
                    [product setObject:trimmedString forKey:[grandchild name]];
                }
            }

            // Add product to current category array
            switch (categoryId) {
                case 0:
                    [self.mobil addObject: product];
                    break;
                case 1:
                    [self.allgemein addObject: product];
                    break;
                case 2:
                    [self.besitzeIch addObject: product];
                    break;
                case 3:
                    [self.willIch addObject: product];
                    break;
                default:
                    break;
            }
            [product release];
        }

    }  

La première fois que j'analyse le code XML, aucune fuite n'apparaît dans les instruments. La prochaine fois, j'ai beaucoup de fuites (NSCFString / NSCFDictionary).
Instruments me renvoie vers cette partie de CXMLNode.m lorsque je creuse un objet qui a fui:

theStringValue = [NSString stringWithUTF8String:(const char *)theXMLString];
if ( _node->type != CXMLTextKind )
   xmlFree(theXMLString);
}

return(theStringValue);  

J'ai vraiment passé beaucoup de temps et j'ai essayé plusieurs approches pour résoudre ce problème, mais sans succès jusqu'à présent, il me manque peut-être quelque chose d'essentiel?

Toute aide est très appréciée, merci!

Était-ce utile?

La solution

Le problème est probablement dans cette ligne:

[self.mobil addObject:[product copy]];

En appelant pour obtenir une copie du produit , vous créez une nouvelle instance NSMutableDictionary avec un nombre de conservations égal à 1. Toutefois, l'instance mobil incrémente la conservation de la copie. compte lorsque vous lui envoyez le message addObject: ; le nombre de copies conservées de la copie est donc de 2. En règle générale, un objet est responsable de la gestion de sa propre mémoire d'objet. Ainsi, chaque fois que vous envoyez un message setFoo: ou addObject: , vous pouvez simplement transmettre l'objet directement, même s'il est auto-supprimé ou si vous prévoyez de le libérer juste après l'appel; Il incombe au destinataire de conserver l'objet que vous passez s'il le tient.

Comme vous n’avez assigné la copie à aucune variable, vous n’avez pas de pointeur que vous pouvez utiliser pour décrémenter le nombre de conservations de la copie maintenant que vous n’êtes plus intéressé, donc même si mobil publie la copie du produit à un moment donné, la copie n'atteindra jamais le nombre de conservations de 0. Votre instruction [version du produit] à la fin de la boucle for libère le produit objet, pas la copie que vous avez créée.

Au lieu de cela, essayez ce qui suit et voyez si les instruments sont plus agréables:

[self.mobil addObject:product];

Autres conseils

En termes simples, chaque fois que vous utilisez copy , vous devez également utiliser release / autorelease quelque part.

Et dans ce cas, la solution encore plus simple consiste à ne pas utiliser copie , car vous ne faites rien avec la version originale de produit après vous l'avez copié.

J'ai résolu le problème moi-même. C'était un peu stupide, mais peut-être que quelqu'un pourrait tomber sur la même chose, alors je vais le poster ici.

1) J'avais un tableau mutable configuré en tant que variables d'instance comme ceci:

@interface XMLParser : NSObject {

// ...  
NSMutableArray *mobil;  
// ...  
}   
@property(nonatomic, retain) NSMutableArray *mobil;  
@end  

Chaque fois que je voulais restaurer de nouvelles données, je le faisais:
    self.mobil = nil;
Ce qui n'a pas ce que je voulais faire, c'est donc la meilleure approche:
    [self.mobil removeAllObjects];

2) La méthode dealloc doit être la suivante pour corriger les fuites (car mobil est défini comme une propriété):
    - (vide) dealloc {
      [version mobile];
      self.mobil = nil;
  }

Ouf, cela a demandé beaucoup de travail - espérons-le, cela fera gagner du temps à quelqu'un d'autre :-)

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