2011-03-02 1 views
1

J'ai écrit une fonction pour renvoyer une chaîne à un chemin de répertoire. J'obtiens un EXC_BAD_ACCESS et je pense que cette fonction est la cause. Ai-je besoin de conserver le nsstring ou quelque chose?obtenir un EXC_BAD_ACCESS lors de l'attribution d'un NSString

-(void) getRemoteFiles:(NSMutableArray *) M 
{ 
    [self createFileToAppDirectory]; 

    if (!networkqueue) { 
     networkqueue:[[[ASINetworkQueue alloc] init] autorelease]; 
    } 

    [[self networkQueue] cancelAllOperations]; 

    [self setNetworkQueue:[ASINetworkQueue queue]]; 
    [[self networkQueue] setDelegate:self]; 
    [[self networkQueue] setRequestDidFinishSelector:@selector(requestFinished:)]; 
    [[self networkQueue] setRequestDidFailSelector:@selector(requestFailed:)]; 
    [[self networkQueue] setQueueDidFinishSelector:@selector(queueFinished:)]; 


    int i; 

    for (i=0; i<[M count]; i++) { 
     NSString *url=[M objectAtIndex:i]; 
     NSString* theFileName = [url lastPathComponent]; 
     NSString *safestring=[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; 
     if ([theFileName isEqualToString:@"nothing"]==NO) { 

      ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:[NSURL URLWithString:safestring]]; 
      //think this is causing the problem 
      NSString *savepath=[self getDirectoryPathForFileName:theFileName]; 
      //[request setDownloadDestinationPath:savepath]; 
      [[self networkQueue] addOperation:request]; 
     } 

    } 

    [[self networkQueue] go]; 
    //error thrown after this point 


} 
-(NSString *)getDirectoryPathForFileName:(NSString *)filename 

{ 
    NSFileManager *filemgr; 
    NSArray *dirPaths; 
    NSString *docsDir; 
    NSString *newDir; 
    BOOL isDir; 


    filemgr =[NSFileManager defaultManager]; 
    dirPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 

    docsDir = [dirPaths objectAtIndex:0]; 

    newDir = [docsDir stringByAppendingPathComponent:@"remix_data"]; 
    if ([filemgr fileExistsAtPath:newDir isDirectory:&isDir]==NO) { 
     NSLog(@"dir should exist but does not... go funt dat"); 
    } 

    NSString *localFilePath = [newDir stringByAppendingPathComponent:filename]; 
    [filemgr release]; 
    [docsDir release]; 
    [newDir release]; 
    return localFilePath; 
} 
+0

Vous ne faites pas alloc/init sur filemgr, docsDir et newDir. Alors pourquoi les libérez-vous? –

+0

J'apprends encore sur la gestion de la mémoire et le code vient d'un exemple. Je suppose que l'exemple est faux? – dubbeat

Répondre

2

Non, vous êtes en train de relâcher. Dans getDirectoryPathForFileName, vous libérez docsDir (par exemple), bien que vous ne l'ayez jamais conservé. Vous l'avez extrait du tableau dirPaths, ce qui n'augmentera pas le nombre de retenues. En le relâchant, vous diminuez le nombre de retenues, éventuellement à zéro, ce qui libérera la chaîne pendant que le tableau pense la maintenir. La prochaine fois que le tableau fait quelque chose avec cette chaîne, votre application va planter. Supprimez simplement les appels de version pour docsDir et newDir et vous devriez être bon ...

+0

Je vais essayer ça. Est-ce que mon utilisation de nsstring vous semble correcte? – dubbeat

+0

Oui, il me semble parfaitement raisonnable, il n'y a aucune occasion où vous l'avez utilisé sans nécessité ou de mauvaise façon. Vous avez juste besoin de vous habituer à ces problèmes de gestion de la mémoire, mais ce n'est pas lié à NSString ... N'ayez pas peur, vous vous habituerez! Une règle de base: vous n'avez besoin de publier quelque chose que si vous l'avez créé en utilisant une méthode qui commence par init ou si vous l'avez conservée manuellement. – Toastor

+0

solution correcte et explication utile – dubbeat

-1

Oui, il est préférable de retenir la chaîne et de la libérer après utilisation. La publication des chaînes docsDir et newDir est également déconseillée car vous ne les attribuez pas. Ce sont des objets à libération automatique.

1

Comme toujours quand quelqu'un a un problème EXC_BAD_ACCESS, je recommande NSZombie. Dans votre cas, il est assez facile de voir pourquoi il plante, puisque vous libérez des choses sans les avoir allouées ou conservées en premier. Vous ne devez publier que des éléments que vous avez alloués ou conservés.

Si vous avez un problème de EXC_BAD_ACCESS à l'avenir, ce n'est pas aussi facile à comprendre, voici comment utiliser NSZombie:

Pour activer NSZombie procédez comme suit:

  1. Informez-vous du exécutable
  2. Accédez à l'onglet arguments.
  3. Dans la section « Variables à l'environnement: » ajouter section:

Nom: NSZombieEnabled Valeur: OUI

Lancez ensuite votre application comme d'habitude et quand il tombe en panne, il devrait vous dire que L'objet désalloué a reçu le message de libération.

+1

et n'oubliez pas de désactiver les zombies par la suite. Vous ne voulez pas traquer les fuites pendant une demi-heure juste pour comprendre que vous avez quitté NSZombies. Comme je l'ai fait hier. –

+0

C'est un bon point. –

Questions connexes