Pregunta

Actualización : edité el código, pero el problema persiste ...

Hola a todos,
esta es mi primera publicación aquí: este lugar me pareció un excelente recurso para resolver muchas de mis preguntas. Normalmente hago mi mejor esfuerzo para arreglar cualquier cosa por mi cuenta, pero esta vez realmente no tengo idea de qué sale mal, así que espero que alguien pueda ayudarme.
Estoy creando una aplicación para iPhone que analiza un par de archivos xml con TouchXML. Tengo una clase XMLParser, que se encarga de descargar y analizar los resultados. Recibo pérdidas de memoria cuando analizo un archivo xml más de una vez con la misma instancia de XMLParser. Este es uno de los fragmentos de análisis (solo la parte relevante):

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 primera vez que analizo el xml no aparece ninguna fuga en los instrumentos, la próxima vez que lo hago, tengo muchas fugas (NSCFString / NSCFDictionary).
Instruments me señala a esta parte dentro de CXMLNode.m , cuando excavo en un objeto filtrado:

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

return(theStringValue);  

Realmente pasé mucho tiempo e intenté varios enfoques para solucionar esto, pero hasta ahora no sirvió de nada, ¿tal vez me estoy perdiendo algo esencial?

Cualquier ayuda es muy apreciada, ¡gracias!

¿Fue útil?

Solución

El problema es probable en esta línea:

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

Al solicitar una copia del producto , está creando una nueva instancia NSMutableDictionary con un recuento de retención de 1. Sin embargo, la instancia mobil incrementará la retención de la copia cuenta cuando le envía el mensaje addObject: , por lo que el conteo retenido de la copia ahora es 2. En términos generales, un objeto es responsable de manejar su propia memoria de objeto, por lo que cada vez que envíe un mensaje a setFoo: o addObject: , puede pasar el objeto directamente, incluso si se ha publicado automáticamente o si planea lanzarlo inmediatamente después de la llamada; es responsabilidad del receptor retener el objeto que está pasando si necesita aferrarse a él.

Debido a que no asignó la copia a ninguna variable, no tiene un puntero que pueda usar para disminuir el conteo de retención de la copia ahora que ya no está interesado en ella, por lo que incluso si mobil libera la copia del producto en algún momento, la copia nunca alcanzará un recuento de retención de 0. Su declaración [product release] al final del ciclo for libera el producto original objeto, no la copia que creó.

En su lugar, intente lo siguiente y vea si los instrumentos son más felices:

[self.mobil addObject:product];

Otros consejos

En términos simples, cada vez que use copy , también debe usar release / autorelease en alguna parte.

Y en este caso, la respuesta aún más fácil es no usar copy en primer lugar, ya que no está haciendo nada con la versión original de product después lo has copiado.

Solucioné el problema yo mismo. Fue un poco estúpido, pero tal vez alguien podría encontrarse con lo mismo, así que voy a publicarlo aquí.

1) Tenía una matriz mutable configurada como variables de instancia como esta:

@interface XMLParser : NSObject {

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

Cada vez que quería restaurar nuevos datos dentro lo hacía:
    self.mobil = nil;
Lo cual no era lo que quería hacer, así que este es el mejor enfoque:
    [self.mobil removeAllObjects];

2) El método dealloc debe ser así para corregir las filtraciones (porque mobil se define como una propiedad):
    - (nulo) dealloc {
      [liberación de mobil];
      self.mobil = nil;
  }

Menos mal, ha sido mucho trabajo descubrir, espero que ahorre algo de tiempo a alguien más :-)

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