2009-11-04 6 views
0

J'ai développé mon application iPhone et maintenant je la teste avec des instruments pour trouver des fuites de mémoire.Quelqu'un peut-il identifier la fuite, aide?

J'ai ma classe appDelegate où je suis aller chercher des données du service Web, puis l'analyser ensuite le stocker dans un tableau ..

Voici ma méthode de applicationDidFinishLaunching:

UIApplication* app = [UIApplication sharedApplication]; 
app.networkActivityIndicatorVisible = YES; 
serviceURL = [[NSUserDefaults standardUserDefaults] stringForKey:@"readOnly_key"]; 
NSLog(@"text = %@",serviceURL); 

if(serviceURL == nil) 
{ 
    //We set the default values from the settings bundle. 

    //Get the bundle path 
    NSString *bPath = [[NSBundle mainBundle] bundlePath]; 
    NSString *settingsPath = [bPath stringByAppendingPathComponent:@"Settings.bundle"]; 
    NSString *plistFile = [settingsPath stringByAppendingPathComponent:@"Root.plist"]; 

    NSDictionary *settingsDictionary = [NSDictionary dictionaryWithContentsOfFile:plistFile]; 
    NSArray *preferencesArray = [settingsDictionary objectForKey:@"PreferenceSpecifiers"]; 

    NSDictionary *item; 

    NSString *textEntry_Key; 
    NSString *readOnly_Key; 


    for(item in preferencesArray) 
    { 
     //Get the key of the item. 
     NSString *keyValue = [item objectForKey:@"Key"]; 

     //Get the default value specified in the plist file. 
     id defaultValue = [item objectForKey:@"DefaultValue"]; 

     if([keyValue isEqualToString:@"textEntry_key"]){ 
      textEntry_Key = defaultValue; 

     } 

     NSLog(@"default value = %@",defaultValue); 
     if([keyValue isEqualToString:@"readOnly_key"]) 
      readOnly_Key = defaultValue; 



    } 

    //Now that we have all the default values. 
    //We will create it here. 
    NSDictionary *appPrerfs = [NSDictionary dictionaryWithObjectsAndKeys: 
           textEntry_Key, @"textEntry_key", 
           readOnly_Key, @"readOnly_key", 

           nil]; 

    [[NSUserDefaults standardUserDefaults] registerDefaults:appPrerfs]; 
    [[NSUserDefaults standardUserDefaults] synchronize]; 

} 

NSURL *url5 = [[NSURL alloc] initWithString:@"http://192.168.0.150/Nirmal/Service.asmx/searchParameterList"]; 
//NSURL *url5 = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@/Service.asmx/searchParameterList"]]; 
NSMutableURLRequest* request6=[NSMutableURLRequest requestWithURL:url5]; 
[request6 setHTTPMethod:@"POST"]; 
[request6 setTimeoutInterval:10]; 
//NSURLResponse *response6=nil; 
// NSError *err6=nil; 
    //NSData *data6=[[NSURLConnection sendSynchronousRequest:request6 returningResponse:&response6 error:&err6] retain]; 
    data2=[NSURLConnection sendSynchronousRequest:request6 returningResponse:nil error:nil]; 
    if(data2 == nil) 
    { 
     UIAlertView* alert = [[UIAlertView alloc]initWithTitle:@"Alert" message:@"The network is not available.\n Please check the Internet connection." delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
     [alert show]; 
     [alert release]; 

    } 
    else 
    { 
     NSXMLParser *xmlParser5 = [[NSXMLParser alloc] initWithData:data2]; 

     //Initialize the delegate. 
     SearchParameterDataParser *searchParameterDataParser = [[SearchParameterDataParser alloc] initSearchParameterDataParser]; 

     //Set delegate 
     [xmlParser5 setDelegate:searchParameterDataParser]; 

     //Start parsing the XML file. 
     @try { 
      // **the leakage line** 
      BOOL success1 = [xmlParser5 parse]; 


      if(success1) 
       NSLog(@"No Errors"); 
      else 
       NSLog(@"Error Error Error!!!"); 
     } 
     @catch (NSException * e) { 
      NSLog(@"Exception in parsing %@ %@",[e name], [e reason]); 
     } 
     //[xmlParser5 release]; 
     [searchParameterDataParser release]; 
     //[xmlParser5 release]; //leakage 
    } 

    [data2 release]; 

et c'est ma classe analyseur:

#import "SearchParameterDataParser.h" 
#import "AppDelegate.h" 
#import "SearchClass.h" 

@implementation SearchParameterDataParser 
-(SearchParameterDataParser *)initSearchParameterDataParser{ 
    [super init]; 
    appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate]; 
    return self; 
} 

- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName 
    namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qualifiedName 
    attributes:(NSDictionary *)attributeDict { 

    if([elementName isEqualToString:@"SearchClass"]) { 
     [appDelegate.tempArray release]; 
     appDelegate.tempArray = [[NSMutableArray alloc] init]; 
     appDelegate.aSearchClass = [[SearchClass alloc]init]; 
    } 


    NSLog(@"Processing Element: %@", elementName); 
} 

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { 

    if(!currentElementValue){ 


     [currentElementValue release]; 
     currentElementValue = [[NSMutableString alloc] initWithString:string]; 
    } 
    else 
     [currentElementValue appendString:string]; 

    NSLog(@"Processing Value: %@", currentElementValue); 

} 

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
    namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { 

    if([elementName isEqualToString:@"SearchClass"]){ 
     [appDelegate.tempArray addObject:appDelegate.aSearchClass]; 

     return; 
    } 
    else 
     [appDelegate.aSearchClass setValue:currentElementValue forKey:elementName]; 




// [currentElementValue release]; 
    currentElementValue = nil; 
} 

- (void) dealloc { 
    [super dealloc];  
    [aSearchClass release]; 
    [currentElementValue release]; 
    //[self release]; 

} 
@end 

J'ai spécifié la ligne de fuite dans le code.

Quelqu'un peut-il me dire ce qui ne va pas ou comment puis-je résoudre la fuite de mémoire ???????

Répondre

3

C'est assez compliqué, comme une suggestion pour nettoyer les choses un peu, essayez de déplacer des trucs de gestion de la mémoire à des méthodes d'accesseur - votre code est jonché de méthodes -release. à savoir,

au lieu de: -

if([elementName isEqualToString:@"SearchClass"]) { 
    [appDelegate.tempArray release]; 
    appDelegate.tempArray = [[NSMutableArray alloc] init]; 
} 

essayer: -

if([elementName isEqualToString:@"SearchClass"]) { 

    appDelegate.tempArray = [NSMutableArray array]; 
} 

appDelegate a une méthode

- (void)setTempArray:(NSMutableArray *)value { 

    if(value!=tempArray){ 
     [tempArray release]; 
     tempArray = [value retain]; 
    } 
} 

ou vous pouvez utiliser un @synthesized méthode d'accesseur pour sauver la morue vous-même. En aparté tempArray est un nom terrible pour une variable d'instance. Notez également que vous libérez l'ancien tempArray chaque fois que vous en créez un nouveau - quand la dernière instance est-elle nettoyée?

Ce n'est toujours pas génial car votre classe d'analyseur ne doit pas accéder directement aux variables d'instance dans appDelegate. Vardiables tempArray et searchClass devraient être privés, mais c'est hors sujet et plus d'un problème de conception.

Où est libéré url5?

Qu'est-ce que c'est censé faire?

if(!currentElementValue){ 
    [currentElementValue release]; 
} 

libérer currentElementValue s'il n'existe pas?

[data2 release]; 

Avez-vous conservé les données2?

- (void) dealloc { 
[super dealloc];  
    [aSearchClass release]; 
    [currentElementValue release]; 
    //[self release]; 

} 

je pensais aSearchClass était une variable d'instance sur appDelegate?

Cela peut ressembler à du nitpicking mais il est beaucoup plus facile de repérer les fuites si votre code est clair et que vous savez exactement ce qui se passe.

+0

Je sais que tempArray n'est pas un bon nom. mais pour l'instant j'ai pris l'appDelegate parce que je charge toutes mes données dans applicationDidDinishLaunching donc j'utilise cette variable dans la classe de l'analyseur et concernant la [version currentElementValue]; et [release2 de données], j'ai publié car je ne connais pas beaucoup de correctifs de mémoire mais partout où j'ai redirigé par les instruments j'ai essayé de résoudre la fuite juste en libérant l'objet car je pense qu'il n'est pas libéré. Si d'autres suggestions vous sont les bienvenus – harshalb

1

Vous devez libérer à la fois url5 et xmlParser5, puisque vous les avez alloués en utilisant alloc.

Vous devez également vous méfier d'appeler release sur les propriétés, car les paramètres standard créés lorsque vous @synthesize une variable d'instance libèrent généralement la valeur précédente de la variable avant de définir la nouvelle valeur.

+0

youv sont à la fois sur url5 et xmlParse5 mais un autre problème que je n'ai pas mentionné ci-dessus est que chaque fois que j'ai essayé de libérer les objets ci-dessus l'application se bloque. Voir J'ai commenté la sortie de xmlParser5 – harshalb

+0

Si vous appelez "release" sur "xmlParse5" deux fois, votre application va planter. Vous devriez l'appeler une fois après avoir appelé "analyser". –

+0

Je l'ai appelé une seule fois. J'essayais juste avant ou après. Ignorer les deux endroits désolé pour la mauvaise impression .. – harshalb