2010-09-08 7 views
0

Pour une raison quelconque quand je relâche le NSArray je reçois l'exception EXC_BAD_ACCESS. Voici la mise en œuvre:NSArray gestion de la mémoire

-(void) loadAllAlphabets 
{ 
    NSBundle *bundle = [NSBundle mainBundle]; 
    NSArray *imagesPath = [[NSArray alloc] init]; 

    imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"]; 

    alphabets = [[NSMutableArray alloc] init]; 

    NSString *fileName = [[NSString alloc] init]; 

    for(int i=0; i<= imagesPath.count -1 ; i++) 
    { 
     fileName = [[imagesPath objectAtIndex:i] lastPathComponent]; 
     CCSprite *sprite = [CCSprite spriteWithFile:fileName]; 

     sprite.userData = [[fileName stringByDeletingPathExtension] uppercaseString]; 

     [alphabets addObject:sprite]; 
    } 

    // release fileName 
    [fileName release]; 
    fileName = nil; 

    [imagesPath release]; // this causes the application to crash with EXC_BAD_ACCESS 
// imagesPath = nil; 

}

MISE À JOUR 1:

Ainsi, le problème est que même si je déversait l'objet imagesPath depuis je alloc que bientôt devenir hors de propos quand pathsForResourcesOfType a renvoyé un objet autorelease. Cela signifie que je ne devrais pas libérer l'objet imagesPath manuellement.

La ligne suivante doit être utilisée:

NSArray *imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"]; 

MISE À JOUR 2:

Une autre question qui est liée à ce poste. Dans le code suivant, j'initialise un nouveau NSMutableArray manuellement.

alphabets = [[NSMutableArray alloc] init]; 

Plus tard, j'insérer CCSprite (objets) en cocos2d tableau alphabets. CCSprite sont des objets autorelease. Dois-je encore publier des alphabets manuellement? Puisque, après un certain temps, tous les objets sont libérés et la mémoire sera retournée, mais que restera-t-il dans le tableau NSMutable des alphabets?

+0

La fuite se produit lorsque vous réaffectez imagesPath à l'appel pathsForResourcesOfType: parce que vous avez déjà alloué et –

Répondre

4

règle générale dans la gestion de la mémoire - vous ne devez libérer un objet que si vous l'avez obtenu en utilisant new, copy ou alloc (la méthode standard suit cette règle et vous devriez y adhérer également).

Dans votre cas, vous obtenir objet imagesPath en utilisant la méthode pathsForResourcesOfType: qui retourne un objet autoreleased de sorte que vous ne devez pas libérer vous-même.

Edit: oui, vous devez libérer alphabets objet quelque part (pour la même raison - que vous avez obtenu avec la méthode alloc).

Les conteneurs Objective-c prennent en charge les objets qui leur sont ajoutés, c'est-à-dire lorsque des objets sont ajoutés à un tableau qu'ils conservent afin de garantir que leur durée de vie est au moins égale à la durée de vie du conteneur. Lorsque vous supprimez un objet de la collection ou de la collection elle-même est détruit, ses membres sont libérés (pour compenser conserver sur ajouter).

+0

Merci Vladimir! Ainsi, même si j'ai alloué les imagesPath les pathsForResourcesOfType ont retourné un objet autorelease que je ne dois pas relâcher manuellement. – azamsharp

6

Je pense que la confusion est ici:

NSArray *imagesPath = [[NSArray alloc] init]; 
imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"]; 

La première ligne crée un nouvel objet. Cet objet a vraiment besoin d'être libéré.

La deuxième ligne sur cet objet-écrit avec un nouvel objet autogérée. Cela ne pas doivent être libérés manuellement.

Cela signifie que vous fuit la première imagesPath.

En général, vous devez libérer un objet si vous alloc ou copy il. Et vous ne devez pas écraser un objet avant de libérer (ou de libérer automatiquement) son contenu.

3

En outre, vous fuite de mémoire que vous initialisez imagesPath avec un tableau non-mutables vide puis défaussez lorsque vous attribuez-il le résultat de pathsForResources: à lui. Il suffit de faire ceci:

NSArray *imagesPath = [bundle pathsForResourcesOfType:@"png" inDirectory:@"Images"]; 

même erreur avec fileName. Pas besoin de l'initialiser avec une chaîne vide non mutable.

Et également ne pas libérer fileName puisqu'il s'agit également d'un objet autoreleased.

+0

La raison pour laquelle fileName est autorelease object est parce qu'elle vient du droit de imagesPath NSArray? – azamsharp

+0

En outre, si j'exécute une boucle et que j'assigne fileName, cela signifie que je crée un nouvel objet de NSString pour chaque compte de boucle. – azamsharp

+0

@azamsharp oui, la valeur de la ligne 'fileName = [[NSString alloc] init];' est rejeté lorsque vous lui attribuez une chaîne auto-libérée à l'intérieur d'une boucle. Personnellement, j'initialiser fileName avec nil avant la boucle – Vladimir